Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OVMi Part2 AtomicPredicates #154

Merged
merged 19 commits into from
May 15, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 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