Skip to main content

ovmi/
executor.rs

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 error.
31    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
40/// convert to error code from error tyoe.
41pub fn codec_error<Address>(expected_type_name: &'static str) -> ExecError<Address> {
42    ExecError::CodecError {
43        type_name: expected_type_name,
44    }
45}
46
47/// Default ExecResult type bool.
48pub type ExecResult<Address> = core::result::Result<bool, ExecError<Address>>;
49/// Generic ExecResult type.
50pub type ExecResultT<T, Address> = core::result::Result<T, ExecError<Address>>;
51/// Generic ExecResult tyoe from Ext.
52pub type ExecResultTOf<T, Ext> = core::result::Result<T, ExecError<AddressOf<Ext>>>;
53/// Address type from external.
54pub type AddressOf<Ext> = <Ext as ExternalCall>::Address;
55/// Hash type from external.
56pub type HashOf<Ext> = <Ext as ExternalCall>::Hash;
57/// Hashing type from external.
58pub type HashingOf<Ext> = <Ext as ExternalCall>::Hashing;
59/// Property type from external.
60pub type PropertyOf<Ext> = Property<<Ext as ExternalCall>::Address>;
61
62/// Maybe Address defines the traits should be implemented.
63pub 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    /// The address type of Plasma child chain (default: AccountId32)
114    type Address: MaybeAddress;
115    /// The hash type of Plasma child chain (default: H256)
116    type Hash: MaybeHash;
117    /// The hashing type of Plasma child chain (default: Keccak256)
118    type Hashing: Hasher<Out = Self::Hash>;
119
120    // relation const any atomic predicate address.
121    /// The address of not predicate address.
122    fn not_address() -> Self::Address;
123    /// The address of and predicate address.
124    fn and_address() -> Self::Address;
125    /// The address of or predicate address.
126    fn or_address() -> Self::Address;
127    /// The address of for all predicate address.
128    fn for_all_address() -> Self::Address;
129    /// The address of there exists predicate address.
130    fn there_exists_address() -> Self::Address;
131    /// The address of equal predicate address.
132    fn equal_address() -> Self::Address;
133    /// The address of is contained predicate address.
134    fn is_contained_address() -> Self::Address;
135    /// The address of is less than  predicate address.
136    fn is_less_address() -> Self::Address;
137    /// The address of is stored predicate address.
138    fn is_stored_address() -> Self::Address;
139    /// The address of is valid signature predicate address.
140    fn is_valid_signature_address() -> Self::Address;
141    /// The address of verify inclusion predicate address.
142    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    /// relation const any signature algorithm.
166    fn secp256k1() -> Self::Hash;
167
168    /// Produce the hash of some codec-encodable value.
169    fn hash_of<S: Encode>(s: &S) -> Self::Hash {
170        Encode::using_encoded(s, Self::Hashing::hash)
171    }
172
173    /// Call (other predicate) into the specified account.
174    fn ext_call(
175        &self,
176        to: &Self::Address,
177        input_data: PredicateCallInputs<Self::Address>,
178    ) -> ExecResultT<Vec<u8>, Self::Address>;
179
180    /// Returns a reference to the account id of the caller.
181    fn ext_caller(&self) -> Self::Address;
182
183    /// Returns a reference to the account id of the current contract.
184    fn ext_address(&self) -> Self::Address;
185
186    /// Notes a call other storage.
187    /// Only return true or false.
188    /// CommitmentAddress(special) isCommitment(address) -> Commitment
189    /// is_stored_predicate(&self, address, key, value);?
190    /// ref: https://github.com/cryptoeconomicslab/ovm-contracts/blob/master/contracts/Predicate/Atomic/IsStoredPredicate.sol
191    fn ext_is_stored(&self, address: &Self::Address, key: &[u8], value: &[u8]) -> bool;
192
193    /// Verify messagge hash with signature and address.
194    /// Should be used by ECDSA.
195    fn ext_verify(&self, hash: &Self::Hash, signature: &[u8], address: &Self::Address) -> bool;
196
197    /// verifyInclusionWithRoot method verifies inclusion proof in Double Layer Tree.
198    /// Must be used by kind of Commitment contract by Plasma module.
199    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    /* Helpers of UniversalAdjudicationContract. */
209    /// `is_decided` function of UniversalAdjudication in OVM module.
210    fn ext_is_decided(&self, property: &PropertyOf<Self>) -> bool;
211    /// `is_decided_by_id` function of UniversalAdjudication in OVM module.
212    fn ext_is_decided_by_id(&self, id: Self::Hash) -> bool;
213    /// `get_property_id` function of UniversalAdjudication in OVM module.
214    fn ext_get_property_id(&self, property: &PropertyOf<Self>) -> Self::Hash;
215    /// `set_predicate_decision` function of UniversalAdjudication in OVM module.
216    fn ext_set_predicate_decision(
217        &self,
218        game_id: Self::Hash,
219        decision: bool,
220    ) -> ExecResult<Self::Address>;
221
222    /* Helpers of UtilsContract. */
223    /// @dev check target is variable or not.
224    /// A variable has prefix V and its length is less than 20.
225    fn is_placeholder(target: &Vec<u8>) -> bool {
226        return target.len() < 20 && target.get(0) == Some(&(b'V' as u8));
227    }
228
229    /// @dev check target is label or not.
230    /// A label has prefix L and its length is less than 20.
231    fn is_label(target: &Vec<u8>) -> bool {
232        return target.len() < 20 && target.get(0) == Some(&(b'L' as u8));
233    }
234
235    /// sub_bytes of [start_idnex, end_idnex).
236    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    /// sub array of [start_idnex, end_idnex).
245    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    /// sub_bytes of [1...).
254    fn get_input_value(target: &Vec<u8>) -> Vec<u8> {
255        Self::sub_bytes(target, 1, target.len() as u128)
256    }
257
258    /// Decoded to u128
259    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    /// Decoded to range
264    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    /// Decoded to Address
269    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    /// Decoded to bool
274    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    /// Decoded to Property
279    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    /// Decoded to Vec<Vec<u8>>
285    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}