Skip to content

Commit

Permalink
OVMi Part2 AtomicPredicates (#154)
Browse files Browse the repository at this point in the history
* WIP: or decidable

* add or

* ovm ext_call is not needed mut

* add all logical and deciable predicates

* WIP: eq

* add AtomicPredicates

* fmt and add lock

* add from_address to executable predicate

* add predicate mock

* fmt

* add tests

* add from_address to executable predicate

* upd lock

* tmp

* fix name

* WIP: is valid signature

* lifetime

* fix lifetime 2
  • Loading branch information
satellitex authored May 15, 2020
1 parent 42df4b8 commit 4db6488
Show file tree
Hide file tree
Showing 22 changed files with 1,410 additions and 118 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions frame/ovm/src/predicate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ where
}

/// Make a call to the specified address, optionally transferring some funds.
pub fn call(&mut self, dest: T::AccountId, input_data: Vec<u8>) -> ExecResult {
pub fn call(&self, dest: T::AccountId, input_data: Vec<u8>) -> ExecResult {
if self.depth == self.config.max_depth as usize {
return Err(ExecError {
reason: "reached maximum depth, cannot make a call".into(),
Expand All @@ -160,7 +160,7 @@ where
};

let caller = self.self_account.clone();
let mut nested = self.nested(dest);
let nested = self.nested(dest);
let executable = try_or_exec_error!(
nested.loader.load_main(&predicate.predicate_hash),
input_data
Expand All @@ -170,13 +170,13 @@ where
.execute(&executable, nested.new_call_context(caller), input_data)
}

fn new_call_context<'b>(&'b mut self, caller: T::AccountId) -> CallContext<'b, 'a, T, V, L> {
fn new_call_context<'b>(&'b self, caller: T::AccountId) -> CallContext<'b, 'a, T, V, L> {
CallContext { ctx: self, caller }
}
}

pub struct CallContext<'a, 'b: 'a, T: Trait + 'b, V: Vm<T> + 'b, L: Loader<T>> {
ctx: &'a mut ExecutionContext<'b, T, V, L>,
ctx: &'a ExecutionContext<'b, T, V, L>,
caller: T::AccountId,
}

Expand All @@ -194,7 +194,7 @@ where
type T = T;

/// Call (possibly other predicate) into the specified account.
fn call(&mut self, to: &AccountIdOf<Self::T>, input_data: Vec<u8>) -> ExecResult {
fn call(&self, to: &AccountIdOf<Self::T>, input_data: Vec<u8>) -> ExecResult {
self.ctx.call(to.clone(), input_data)
}

Expand Down
2 changes: 1 addition & 1 deletion frame/ovm/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub trait Ext {
type T: Trait;

/// Call (possibly other predicate) into the specified account.
fn call(&mut self, to: &AccountIdOf<Self::T>, input_data: Vec<u8>) -> ExecResult;
fn call(&self, to: &AccountIdOf<Self::T>, input_data: Vec<u8>) -> ExecResult;

/// Returns a reference to the account id of the caller.
fn caller(&self) -> &AccountIdOf<Self::T>;
Expand Down
1 change: 1 addition & 0 deletions ovmi/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ hash-db = { version = "0.15", optional = true }
[dev-dependencies]
primitive-types = { version = "0.7" }
sp-runtime = "2.0.0-alpha.6"
hex = "0.4"

[features]
default = ["std"]
Expand Down
120 changes: 100 additions & 20 deletions ovmi/lib/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ use core::marker::PhantomData;
pub use hash_db::Hasher;
use snafu::{ResultExt, Snafu};

#[derive(Snafu)]
#[derive(Snafu, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ExecError<Address> {
#[snafu(display("Require error: {}", msg))]
Require { msg: &'static str },
Require {
msg: &'static str,
},
#[snafu(display(
"Can not call method error: you call {}, expected {}",
call_method,
Expand All @@ -21,10 +23,19 @@ pub enum ExecError<Address> {
call_method: PredicateCallInputs<Address>,
expected: &'static str,
},
#[snafu(display("Can not call address error."))]
CallAddress {
address: Address,
},
#[snafu(display("Codec error: type name is {}", type_name))]
CodecError { type_name: &'static str },
CodecError {
type_name: &'static str,
},
#[snafu(display("Unexpected error: {}", msg))]
Unexpected { msg: &'static str },
Unexpected {
msg: &'static str,
},
Unimplemented,
}

pub type ExecResult<Address> = core::result::Result<bool, ExecError<Address>>;
Expand All @@ -34,8 +45,8 @@ pub type HashOf<Ext> = <Ext as ExternalCall>::Hash;
pub type HashingOf<Ext> = <Ext as ExternalCall>::Hashing;
pub type PropertyOf<Ext> = Property<<Ext as ExternalCall>::Address>;

pub trait MaybeAddress: Codec + Debug + Clone + Eq + PartialEq {}
impl<T: Codec + Debug + Clone + Eq + PartialEq> MaybeAddress for T {}
pub trait MaybeAddress: Codec + Debug + Clone + Eq + PartialEq + Default {}
impl<T: Codec + Debug + Clone + Eq + PartialEq + Default> MaybeAddress for T {}

pub trait MaybeHash:
AsRef<[u8]>
Expand Down Expand Up @@ -77,8 +88,20 @@ pub trait ExternalCall {
type Hashing: Hasher<Out = Self::Hash>;

// relation const any atomic predicate address.
const NotPredicate: Self::Address;
const AndPredicate: Self::Address;
const NOT_ADDRESS: Self::Address;
const AND_ADDRESS: Self::Address;
const OR_ADDRESS: Self::Address;
const FOR_ALL_ADDRESS: Self::Address;
const THERE_EXISTS_ADDRESS: Self::Address;
const EQUAL_ADDRESS: Self::Address;
const IS_CONTAINED_ADDRESS: Self::Address;
const IS_LESS_ADDRESS: Self::Address;
const IS_STORED_ADDRESS: Self::Address;
const IS_VALID_SIGNATURE_ADDRESS: Self::Address;
const VERIFY_INCLUAION_ADDRESS: Self::Address;

// relation const any signature algorithm.
// const SECP_256_K1: Self::Hash;

/// Produce the hash of some codec-encodable value.
fn hash_of<S: Encode>(s: &S) -> Self::Hash {
Expand All @@ -87,7 +110,7 @@ pub trait ExternalCall {

/// Call (other predicate) into the specified account.
fn ext_call(
&mut self,
&self,
to: &Self::Address,
input_data: PredicateCallInputs<Self::Address>,
) -> ExecResult<Self::Address>;
Expand All @@ -101,9 +124,20 @@ pub trait ExternalCall {
/// Notes a call other storage.
/// Only return true or false.
/// CommitmentAddress(special) isCommitment(address) -> Commitment
/// is_stored_predicate(&mut self, address, key, value);?
/// is_stored_predicate(&self, address, key, value);?
/// ref: https://github.com/cryptoeconomicslab/ovm-contracts/blob/master/contracts/Predicate/Atomic/IsStoredPredicate.sol
fn ext_is_stored(&mut self, address: &Self::Address, key: &[u8], value: &[u8]) -> bool;
fn ext_is_stored(&self, address: &Self::Address, key: &[u8], value: &[u8]) -> bool;

/// verifyInclusionWithRoot method verifies inclusion proof in Double Layer Tree.
/// Must be used by kind of Commitment contract by Plasma module.
fn ext_verify_inclusion_with_root(
&self,
leaf: Self::Hash,
token_address: Self::Address,
range: &[u8],
inclusion_proof: &[u8],
root: &[u8],
) -> bool;

/* Helpers of UniversalAdjudicationContract. */
/// `is_decided` function of UniversalAdjudication in OVM module.
Expand All @@ -116,8 +150,51 @@ pub trait ExternalCall {
game_id: Self::Hash,
decision: bool,
) -> ExecResult<Self::Address>;
}

/* Helpers of UtilsContract. */
/// @dev check target is variable or not.
/// A variable has prefix V and its length is less than 20.
fn is_placeholder(target: &Vec<u8>) -> bool {
return target.len() < 20 && target.get(0) == Some(&(b'V' as u8));
}

/// @dev check target is label or not.
/// A label has prefix L and its length is less than 20.
fn is_label(target: &Vec<u8>) -> bool {
return target.len() < 20 && target.get(0) == Some(&(b'L' as u8));
}

/// sub_bytes of [start_idnex, end_idnex).
fn sub_bytes(target: &Vec<u8>, start_index: u128, end_index: u128) -> Vec<u8> {
target
.as_slice()
.get((start_index as usize)..(end_index as usize))
.unwrap_or(vec![].as_slice())
.to_vec()
}

/// sub_bytes of [1...).
fn get_input_value(target: &Vec<u8>) -> Vec<u8> {
Self::sub_bytes(target, 1, target.len() as u128)
}

/// Decoded to u128
fn bytes_to_u128(target: &Vec<u8>) -> ExecResultT<u128, Self::Address> {
Decode::decode(&mut &target[..]).map_err(|_| ExecError::CodecError { type_name: "u128" })
}

/// Decoded to range
fn bytes_to_range(target: &Vec<u8>) -> ExecResultT<Range, Self::Address> {
Decode::decode(&mut &target[..]).map_err(|_| ExecError::CodecError { type_name: "Range" })
}

/// Decoded to Address
fn bytes_to_address(target: &Vec<u8>) -> ExecResultT<Self::Address, Self::Address> {
Decode::decode(&mut &target[..]).map_err(|_| ExecError::CodecError {
type_name: "Address",
})
}
}
pub trait OvmExecutor<P> {
type ExtCall: ExternalCall;
fn execute(
Expand All @@ -126,13 +203,13 @@ pub trait OvmExecutor<P> {
) -> ExecResult<AddressOf<Self::ExtCall>>;
}

pub struct AtomicExecutor<P, Ext> {
pub struct BaseAtomicExecutor<P, Ext> {
_phantom: PhantomData<(P, Ext)>,
}

impl<P, Ext> OvmExecutor<P> for AtomicExecutor<P, Ext>
impl<P, Ext> OvmExecutor<P> for BaseAtomicExecutor<P, Ext>
where
P: predicates::AtomicPredicateInterface<AddressOf<Ext>>,
P: predicates::BaseAtomicPredicateInterface<AddressOf<Ext>>,
Ext: ExternalCall,
{
type ExtCall = Ext;
Expand All @@ -141,20 +218,23 @@ where
call_method: PredicateCallInputs<AddressOf<Ext>>,
) -> ExecResult<AddressOf<Ext>> {
match call_method {
PredicateCallInputs::AtomicPredicate(atomic) => {
PredicateCallInputs::BaseAtomicPredicate(atomic) => {
match atomic {
AtomicPredicateCallInputs::Decide { inputs } => {
BaseAtomicPredicateCallInputs::Decide { inputs } => {
return predicate.decide(inputs);
}
AtomicPredicateCallInputs::DecideTrue { inputs } => {
predicate.decide_true(inputs);
BaseAtomicPredicateCallInputs::DecideTrue { inputs } => {
predicate.decide_true(inputs)?;
return Ok(true);
}
BaseAtomicPredicateCallInputs::DecideWithWitness { inputs, witness } => {
return predicate.decide_with_witness(inputs, witness);
}
};
}
other => Err(ExecError::CallMethod {
call_method: other,
expected: "AtomicPredicateCallInputs",
expected: "BaseAtomicPredicateCallInputs",
}),
}
}
Expand Down
14 changes: 11 additions & 3 deletions ovmi/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,7 @@ macro_rules! require {
macro_rules! require_with_message {
($val:expr, $message:expr) => {
if !($val) {
return Err(crate::executor::ExecError::Require {
msg: r#"Required error by: $val, message: $message"#,
});
return Err(crate::executor::ExecError::Require { msg: $message });
}
};
}
Expand All @@ -133,10 +131,20 @@ use codec::{Decode, Encode};
pub use compiled_predicates::CompiledPredicate;
pub use prepare::compile_from_json;

#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;

/// An opaque 32-byte cryptographic identifier.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Hash))]
pub struct AccountId([u8; 32]);

/// An opaque Range(u128, u128).
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Hash))]
pub struct Range {
pub start: u128,
pub end: u128,
}
Loading

0 comments on commit 4db6488

Please sign in to comment.