Skip to main content

ovmi/predicates/
mod.rs

1//! # Executable Predicates.
2//! Executable Predicates instanced from Compiled Predicates and Atomic Predicates.
3//!
4//!
5use crate::executor::{AddressOf, ExecError, ExecResult, ExecResultT, ExternalCall, HashOf};
6use alloc::{collections::btree_map::BTreeMap, vec::Vec};
7use codec::{Decode, Encode};
8use core::fmt;
9
10mod and;
11mod executable;
12mod for_all;
13mod not;
14mod or;
15mod there_exists;
16
17pub use and::AndPredicate;
18pub use executable::CompiledExecutable;
19pub use for_all::ForAllPredicate;
20pub use not::NotPredicate;
21pub use or::OrPredicate;
22pub use there_exists::ThereExistsPredicate;
23
24mod equal;
25mod is_contained;
26mod is_less;
27mod is_stored;
28mod is_valid_signature;
29mod verify_inclusion;
30pub use equal::EqualPredicate;
31pub use is_contained::IsContainedPredicate;
32pub use is_less::IsLessThanPredicate;
33pub use is_stored::IsStoredPredicate;
34pub use is_valid_signature::IsValidSignaturePredicate;
35pub use verify_inclusion::VerifyInclusionPredicate;
36
37pub enum AtomicExecutable<'a, Ext: ExternalCall> {
38    Equal(EqualPredicate<'a, Ext>),
39    IsContained(IsContainedPredicate<'a, Ext>),
40    IsLess(IsLessThanPredicate<'a, Ext>),
41    IsStored(IsStoredPredicate<'a, Ext>),
42    IsValidSignature(IsValidSignaturePredicate<'a, Ext>),
43    VerifyInclusion(VerifyInclusionPredicate<'a, Ext>),
44}
45
46impl<Ext: ExternalCall> AtomicPredicateInterface<AddressOf<Ext>> for AtomicExecutable<'_, Ext> {
47    fn decide(&self, inputs: Vec<Vec<u8>>) -> ExecResult<AddressOf<Ext>> {
48        match self {
49            AtomicExecutable::Equal(p) => p.decide(inputs),
50            AtomicExecutable::IsContained(p) => p.decide(inputs),
51            AtomicExecutable::IsLess(p) => p.decide(inputs),
52            AtomicExecutable::IsStored(p) => p.decide(inputs),
53            AtomicExecutable::IsValidSignature(p) => p.decide(inputs),
54            AtomicExecutable::VerifyInclusion(p) => p.decide(inputs),
55        }
56    }
57
58    fn decide_true(&self, inputs: Vec<Vec<u8>>) -> ExecResult<AddressOf<Ext>> {
59        match self {
60            AtomicExecutable::Equal(p) => p.decide_true(inputs),
61            AtomicExecutable::IsContained(p) => p.decide_true(inputs),
62            AtomicExecutable::IsLess(p) => p.decide_true(inputs),
63            AtomicExecutable::IsStored(p) => p.decide_true(inputs),
64            AtomicExecutable::IsValidSignature(p) => p.decide_true(inputs),
65            AtomicExecutable::VerifyInclusion(p) => p.decide_true(inputs),
66        }
67    }
68}
69
70impl<Ext: ExternalCall> AtomicHelperInterface<AddressOf<Ext>> for AtomicExecutable<'_, Ext> {
71    type Hash = HashOf<Ext>;
72    fn ext_address(&self) -> AddressOf<Ext> {
73        AddressOf::<Ext>::default()
74    }
75    fn ext_set_predicate_decision(
76        &self,
77        _game_id: Self::Hash,
78        _decision: bool,
79    ) -> ExecResult<AddressOf<Ext>> {
80        Err(ExecError::Unimplemented)
81    }
82    fn ext_get_property_id(&self, _property: &Property<AddressOf<Ext>>) -> Self::Hash {
83        Self::Hash::default()
84    }
85}
86
87pub enum LogicalConnectiveExecutable<'a, Ext: ExternalCall> {
88    And(AndPredicate<'a, Ext>),
89    Not(NotPredicate<'a, Ext>),
90    Or(OrPredicate<'a, Ext>),
91    ForAll(ForAllPredicate<'a, Ext>),
92    ThereExists(ThereExistsPredicate<'a, Ext>),
93}
94
95impl<Ext: ExternalCall> LogicalConnectiveInterface<AddressOf<Ext>>
96    for LogicalConnectiveExecutable<'_, Ext>
97{
98    fn is_valid_challenge(
99        &self,
100        inputs: Vec<Vec<u8>>,
101        challenge_inputs: Vec<Vec<u8>>,
102        challenge: Property<AddressOf<Ext>>,
103    ) -> ExecResult<AddressOf<Ext>> {
104        match self {
105            LogicalConnectiveExecutable::And(and) => {
106                and.is_valid_challenge(inputs, challenge_inputs, challenge)
107            }
108            LogicalConnectiveExecutable::Not(not) => {
109                not.is_valid_challenge(inputs, challenge_inputs, challenge)
110            }
111            LogicalConnectiveExecutable::Or(or) => {
112                or.is_valid_challenge(inputs, challenge_inputs, challenge)
113            }
114            LogicalConnectiveExecutable::ForAll(for_all) => {
115                for_all.is_valid_challenge(inputs, challenge_inputs, challenge)
116            }
117            LogicalConnectiveExecutable::ThereExists(there_exists) => {
118                there_exists.is_valid_challenge(inputs, challenge_inputs, challenge)
119            }
120        }
121    }
122}
123
124pub enum DecidableExecutable<'a, Ext: ExternalCall> {
125    And(AndPredicate<'a, Ext>),
126    Not(NotPredicate<'a, Ext>),
127    Or(OrPredicate<'a, Ext>),
128    ForAll(ForAllPredicate<'a, Ext>),
129    ThereExists(ThereExistsPredicate<'a, Ext>),
130    Equal(EqualPredicate<'a, Ext>),
131    IsContained(IsContainedPredicate<'a, Ext>),
132    IsLess(IsLessThanPredicate<'a, Ext>),
133    IsStored(IsStoredPredicate<'a, Ext>),
134    IsValidSignature(IsValidSignaturePredicate<'a, Ext>),
135    VerifyInclusion(VerifyInclusionPredicate<'a, Ext>),
136}
137
138impl<Ext: ExternalCall> DecidablePredicateInterface<AddressOf<Ext>>
139    for DecidableExecutable<'_, Ext>
140{
141    fn decide_with_witness(
142        &self,
143        inputs: Vec<Vec<u8>>,
144        witness: Vec<Vec<u8>>,
145    ) -> ExecResult<AddressOf<Ext>> {
146        match self {
147            DecidableExecutable::And(p) => p.decide_with_witness(inputs, witness),
148            DecidableExecutable::Not(p) => p.decide_with_witness(inputs, witness),
149            DecidableExecutable::Or(p) => p.decide_with_witness(inputs, witness),
150            DecidableExecutable::ForAll(p) => p.decide_with_witness(inputs, witness),
151            DecidableExecutable::ThereExists(p) => p.decide_with_witness(inputs, witness),
152            DecidableExecutable::Equal(p) => p.decide_with_witness(inputs, witness),
153            DecidableExecutable::IsContained(p) => p.decide_with_witness(inputs, witness),
154            DecidableExecutable::IsLess(p) => p.decide_with_witness(inputs, witness),
155            DecidableExecutable::IsStored(p) => p.decide_with_witness(inputs, witness),
156            DecidableExecutable::IsValidSignature(p) => p.decide_with_witness(inputs, witness),
157            DecidableExecutable::VerifyInclusion(p) => p.decide_with_witness(inputs, witness),
158        }
159    }
160}
161
162pub enum BaseAtomicExecutable<'a, Ext: ExternalCall> {
163    Equal(EqualPredicate<'a, Ext>),
164    IsContained(IsContainedPredicate<'a, Ext>),
165    IsLess(IsLessThanPredicate<'a, Ext>),
166    IsStored(IsStoredPredicate<'a, Ext>),
167    IsValidSignature(IsValidSignaturePredicate<'a, Ext>),
168    VerifyInclusion(VerifyInclusionPredicate<'a, Ext>),
169}
170
171impl<Ext: ExternalCall> DecidablePredicateInterface<AddressOf<Ext>>
172    for BaseAtomicExecutable<'_, Ext>
173{
174    fn decide_with_witness(
175        &self,
176        inputs: Vec<Vec<u8>>,
177        witness: Vec<Vec<u8>>,
178    ) -> ExecResult<AddressOf<Ext>> {
179        match self {
180            BaseAtomicExecutable::Equal(p) => p.decide_with_witness(inputs, witness),
181            BaseAtomicExecutable::IsContained(p) => p.decide_with_witness(inputs, witness),
182            BaseAtomicExecutable::IsLess(p) => p.decide_with_witness(inputs, witness),
183            BaseAtomicExecutable::IsStored(p) => p.decide_with_witness(inputs, witness),
184            BaseAtomicExecutable::IsValidSignature(p) => p.decide_with_witness(inputs, witness),
185            BaseAtomicExecutable::VerifyInclusion(p) => p.decide_with_witness(inputs, witness),
186        }
187    }
188}
189
190impl<Ext: ExternalCall> AtomicPredicateInterface<AddressOf<Ext>> for BaseAtomicExecutable<'_, Ext> {
191    fn decide(&self, inputs: Vec<Vec<u8>>) -> ExecResult<AddressOf<Ext>> {
192        match self {
193            BaseAtomicExecutable::Equal(p) => p.decide(inputs),
194            BaseAtomicExecutable::IsContained(p) => p.decide(inputs),
195            BaseAtomicExecutable::IsLess(p) => p.decide(inputs),
196            BaseAtomicExecutable::IsStored(p) => p.decide(inputs),
197            BaseAtomicExecutable::IsValidSignature(p) => p.decide(inputs),
198            BaseAtomicExecutable::VerifyInclusion(p) => p.decide(inputs),
199        }
200    }
201
202    fn decide_true(&self, inputs: Vec<Vec<u8>>) -> ExecResult<AddressOf<Ext>> {
203        match self {
204            BaseAtomicExecutable::Equal(p) => p.decide_true(inputs),
205            BaseAtomicExecutable::IsContained(p) => p.decide_true(inputs),
206            BaseAtomicExecutable::IsLess(p) => p.decide_true(inputs),
207            BaseAtomicExecutable::IsStored(p) => p.decide_true(inputs),
208            BaseAtomicExecutable::IsValidSignature(p) => p.decide_true(inputs),
209            BaseAtomicExecutable::VerifyInclusion(p) => p.decide_true(inputs),
210        }
211    }
212}
213
214impl<Ext: ExternalCall> BaseAtomicPredicateInterface<AddressOf<Ext>>
215    for BaseAtomicExecutable<'_, Ext>
216{
217}
218
219impl<Ext: ExternalCall> AtomicHelperInterface<AddressOf<Ext>> for BaseAtomicExecutable<'_, Ext> {
220    type Hash = HashOf<Ext>;
221    fn ext_address(&self) -> AddressOf<Ext> {
222        AddressOf::<Ext>::default()
223    }
224    fn ext_set_predicate_decision(
225        &self,
226        _game_id: Self::Hash,
227        _decision: bool,
228    ) -> ExecResult<AddressOf<Ext>> {
229        Err(ExecError::Unimplemented)
230    }
231    fn ext_get_property_id(&self, _property: &Property<AddressOf<Ext>>) -> Self::Hash {
232        Self::Hash::default()
233    }
234}
235
236#[derive(Clone, Eq, PartialEq, Encode, Decode, Hash)]
237#[cfg_attr(feature = "std", derive(Debug))]
238pub enum PredicateCallInputs<Address> {
239    AtomicPredicate(AtomicPredicateCallInputs),
240    DecidablePredicate(DecidablePredicateCallInputs),
241    LogicalConnective(LogicalConnectiveCallInputs<Address>),
242    BaseAtomicPredicate(BaseAtomicPredicateCallInputs),
243    CompiledPredicate(CompiledPredicateCallInputs<Address>),
244}
245
246#[derive(Clone, Eq, PartialEq, Encode, Decode, Hash)]
247#[cfg_attr(feature = "std", derive(Debug))]
248pub enum AtomicPredicateCallInputs {
249    DecideTrue { inputs: Vec<Vec<u8>> },
250    Decide { inputs: Vec<Vec<u8>> },
251}
252
253impl fmt::Display for AtomicPredicateCallInputs {
254    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
255        let state = match self {
256            AtomicPredicateCallInputs::Decide { inputs: _ } => "Decide",
257            AtomicPredicateCallInputs::DecideTrue { inputs: _ } => "DecideTrue",
258        };
259        write!(f, "{}", state)
260    }
261}
262
263#[derive(Clone, Eq, PartialEq, Encode, Decode, Hash)]
264#[cfg_attr(feature = "std", derive(Debug))]
265pub enum DecidablePredicateCallInputs {
266    DecideWithWitness {
267        inputs: Vec<Vec<u8>>,
268        witness: Vec<Vec<u8>>,
269    },
270}
271
272impl fmt::Display for DecidablePredicateCallInputs {
273    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
274        let state = match self {
275            DecidablePredicateCallInputs::DecideWithWitness {
276                inputs: _,
277                witness: _,
278            } => "DecideWithWitness",
279        };
280        write!(f, "{}", state)
281    }
282}
283
284#[derive(Clone, Eq, PartialEq, Encode, Decode, Hash)]
285#[cfg_attr(feature = "std", derive(Debug))]
286pub enum LogicalConnectiveCallInputs<Address> {
287    IsValidChallenge {
288        inputs: Vec<Vec<u8>>,
289        challenge_inputs: Vec<Vec<u8>>,
290        challenge: Property<Address>,
291    },
292}
293
294impl<Address> fmt::Display for LogicalConnectiveCallInputs<Address> {
295    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
296        let state = match self {
297            LogicalConnectiveCallInputs::IsValidChallenge {
298                inputs: _,
299                challenge_inputs: _,
300                challenge: _,
301            } => "IsValidChallenge",
302        };
303        write!(f, "{}", state)
304    }
305}
306
307#[derive(Clone, Eq, PartialEq, Encode, Decode, Hash)]
308#[cfg_attr(feature = "std", derive(Debug))]
309pub enum BaseAtomicPredicateCallInputs {
310    Decide {
311        inputs: Vec<Vec<u8>>,
312    },
313    DecideWithWitness {
314        inputs: Vec<Vec<u8>>,
315        witness: Vec<Vec<u8>>,
316    },
317    DecideTrue {
318        inputs: Vec<Vec<u8>>,
319    },
320}
321
322impl fmt::Display for BaseAtomicPredicateCallInputs {
323    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
324        let state = match self {
325            BaseAtomicPredicateCallInputs::Decide { inputs: _ } => "Decide",
326            BaseAtomicPredicateCallInputs::DecideTrue { inputs: _ } => "DecideTrue",
327            BaseAtomicPredicateCallInputs::DecideWithWitness {
328                inputs: _,
329                witness: _,
330            } => "DecideWithWitness",
331        };
332        write!(f, "{}", state)
333    }
334}
335
336#[derive(Clone, Eq, PartialEq, Encode, Decode, Hash)]
337#[cfg_attr(feature = "std", derive(Debug))]
338pub enum CompiledPredicateCallInputs<Address> {
339    IsValidChallenge {
340        inputs: Vec<Vec<u8>>,
341        challenge_inputs: Vec<Vec<u8>>,
342        challenge: Property<Address>,
343    },
344    Decide {
345        inputs: Vec<Vec<u8>>,
346        witness: Vec<Vec<u8>>,
347    },
348    DecideTrue {
349        inputs: Vec<Vec<u8>>,
350        witness: Vec<Vec<u8>>,
351    },
352    DecideWithWitness {
353        inputs: Vec<Vec<u8>>,
354        witness: Vec<Vec<u8>>,
355    },
356    GetChild {
357        inputs: Vec<Vec<u8>>,
358        challenge_input: Vec<Vec<u8>>,
359    },
360}
361
362impl<Address> fmt::Display for CompiledPredicateCallInputs<Address> {
363    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
364        let state = match self {
365            CompiledPredicateCallInputs::IsValidChallenge {
366                inputs: _,
367                challenge_inputs: _,
368                challenge: _,
369            } => "IsValidChallenge",
370            CompiledPredicateCallInputs::Decide {
371                inputs: _,
372                witness: _,
373            } => "Decide",
374            CompiledPredicateCallInputs::DecideTrue {
375                inputs: _,
376                witness: _,
377            } => "DecideTrue",
378            CompiledPredicateCallInputs::DecideWithWitness {
379                inputs: _,
380                witness: _,
381            } => "DecideWithWitness",
382            CompiledPredicateCallInputs::GetChild {
383                inputs: _,
384                challenge_input: _,
385            } => "GetChild",
386        };
387        write!(f, "{}", state)
388    }
389}
390
391/// Property stands for dispute logic and we can claim every Properties to Adjudicator Contract.
392/// Property has its predicate address and array of input.
393#[derive(Encode, Decode, Clone, PartialEq, Eq, Hash)]
394#[cfg_attr(feature = "std", derive(Debug))]
395pub struct Property<Address> {
396    /// Indicates the address of Predicate.
397    predicate_address: Address,
398    /// Every input are bytes. Each Atomic Predicate decode inputs to the specific type.
399    inputs: Vec<Vec<u8>>,
400}
401
402pub trait UniversalAdjudication<Hash> {
403    fn ext_set_predicate_decision(&self, game_id: Hash, decision: bool);
404}
405
406pub trait Utils<Hash> {
407    fn ext_get_property_id(&self) -> Hash;
408}
409
410pub trait BaseAtomicPredicateInterface<Address>:
411    AtomicPredicateInterface<Address> + DecidablePredicateInterface<Address>
412{
413}
414
415pub trait AtomicPredicateInterface<Address>: AtomicHelperInterface<Address> {
416    fn decide(&self, _inputs: Vec<Vec<u8>>) -> ExecResult<Address> {
417        return Ok(false);
418    }
419
420    fn decide_true(&self, inputs: Vec<Vec<u8>>) -> ExecResult<Address> {
421        let result_of_decide = AtomicPredicateInterface::decide(self, inputs.clone())?;
422        require_with_message!(result_of_decide, "must decide true");
423        let property = Property {
424            predicate_address: self.ext_address(),
425            inputs: inputs,
426        };
427        self.ext_set_predicate_decision(self.ext_get_property_id(&property), true)?;
428        Ok(true)
429    }
430}
431
432pub trait AtomicHelperInterface<Address> {
433    type Hash;
434    fn ext_address(&self) -> Address;
435    fn ext_set_predicate_decision(
436        &self,
437        game_id: Self::Hash,
438        decision: bool,
439    ) -> ExecResult<Address>;
440    fn ext_get_property_id(&self, property: &Property<Address>) -> Self::Hash;
441}
442
443pub trait DecidablePredicateInterface<Address> {
444    fn decide_with_witness(
445        &self,
446        _inputs: Vec<Vec<u8>>,
447        _witness: Vec<Vec<u8>>,
448    ) -> ExecResult<Address>;
449}
450
451pub trait CompiledPredicateInterface<Address> {
452    fn payout_contract_address(&self) -> Address;
453
454    fn is_valid_challenge(
455        &self,
456        _inputs: Vec<Vec<u8>>,
457        _challenge_inputs: Vec<Vec<u8>>,
458        _challenge: Property<Address>,
459    ) -> ExecResult<Address>;
460
461    /// @dev get valid child property of game tree with challenge_inputs
462    fn get_child(
463        &self,
464        inputs: Vec<Vec<u8>>,
465        challenge_input: Vec<Vec<u8>>,
466    ) -> ExecResultT<Property<Address>, Address>;
467
468    fn decide(&self, _inputs: Vec<Vec<u8>>, _witness: Vec<Vec<u8>>) -> ExecResult<Address>;
469    fn decide_true(&self, _inputs: Vec<Vec<u8>>, _witness: Vec<Vec<u8>>) -> ExecResult<Address>;
470    fn decide_with_witness(
471        &self,
472        _inputs: Vec<Vec<u8>>,
473        _witness: Vec<Vec<u8>>,
474    ) -> ExecResult<Address>;
475}
476
477pub trait LogicalConnectiveInterface<Address> {
478    fn is_valid_challenge(
479        &self,
480        _inputs: Vec<Vec<u8>>,
481        _challenge_inputs: Vec<Vec<u8>>,
482        _challenge: Property<Address>,
483    ) -> ExecResult<Address>;
484}