Commit b84fe874 authored by Hero Bird's avatar Hero Bird
Browse files

[pdsl_core] Add environmental types to Env trait with EnvTypes trait

parent dbd515a2
......@@ -27,8 +27,7 @@
//! To enable the test environment the `test-env` crate feature
//! has to be enabled.
#[cfg(not(feature = "test-env"))]
mod srml_env;
pub mod srml;
#[cfg(feature = "test-env")]
mod test_env;
......@@ -38,10 +37,22 @@ use crate::{
memory::vec::Vec
};
/// The evironment API usable by SRML contracts.
pub trait Env {
use parity_codec::Codec;
/// The environmental types usable by contracts defined with pDSL.
pub trait EnvTypes {
/// The type of an address.
type Address: Codec + PartialEq + Eq;
/// The type of balances.
type Balance: Codec;
// /// The type of gas.
// type Gas: Codec;
}
/// The evironment API usable by contracts defined with pDSL.
pub trait Env: EnvTypes {
/// Returns the chain address of the caller.
fn caller() -> Vec<u8>;
fn caller() -> <Self as EnvTypes>::Address;
/// Stores the given value under the given key.
///
/// # Safety
......@@ -73,7 +84,7 @@ pub trait Env {
}
#[cfg(not(feature = "test-env"))]
pub use self::srml_env::SrmlEnv;
pub use self::srml::SrmlEnv;
#[cfg(feature = "test-env")]
pub use self::test_env::TestEnv;
......@@ -87,7 +98,7 @@ pub use self::test_env::TestEnv;
/// that can be inspected by the user and used
/// for testing contracts off-chain.
#[cfg(not(feature = "test-env"))]
pub type ContractEnv = self::srml_env::SrmlEnv;
pub type ContractEnv = self::srml::DefaultSrmlEnv;
/// The environment implementation that is currently being used.
#[cfg(feature = "test-env")]
......
......@@ -14,72 +14,69 @@
// You should have received a copy of the GNU General Public License
// along with pDSL. If not, see <http://www.gnu.org/licenses/>.
use super::*;
use crate::memory::vec::Vec;
/// Refer to substrate SRML contract module for more documentation.
pub mod c_abi {
extern "C" {
pub fn ext_create(
init_code_ptr: u32,
init_code_len: u32,
gas: u64,
value_ptr: u32,
value_len: u32,
input_data_ptr: u32,
input_data_len: u32
) -> u32;
pub fn ext_call(
callee_ptr: u32,
callee_len: u32,
gas: u64,
value_ptr: u32,
value_len: u32,
input_data_ptr: u32,
input_data_len: u32
) -> u32;
pub fn ext_caller();
pub fn ext_set_storage(
key_ptr: u32,
value_non_null: u32,
value_ptr: u32,
value_len: u32
);
pub fn ext_get_storage(key_ptr: u32) -> u32;
pub fn ext_scratch_size() -> u32;
pub fn ext_scratch_copy(dest_ptr: u32, offset: u32, len: u32);
use crate::{
env::{
srml::{
self,
sys,
},
EnvTypes,
Env,
},
storage::{
Key,
},
memory::vec::Vec,
};
use core::marker::PhantomData;
/// The SRML fundamental types.
pub struct DefaultSrmlTypes;
impl EnvTypes for DefaultSrmlTypes {
type Address = srml::Address;
type Balance = srml::Balance;
}
pub fn ext_input_size() -> u32;
pub fn ext_input_copy(dest_ptr: u32, offset: u32, len: u32);
/// The default SRML environment.
pub type DefaultSrmlEnv = SrmlEnv<DefaultSrmlTypes>;
pub fn ext_return(data_ptr: u32, data_len: u32) -> !;
}
/// The SRML contracts environment.
pub struct SrmlEnv<T>
where
T: EnvTypes
{
marker: PhantomData<T>
}
/// The default SRML contracts environment.
pub struct SrmlEnv;
impl<T> EnvTypes for SrmlEnv<T>
where
T: EnvTypes
{
type Address = <T as EnvTypes>::Address;
type Balance = <T as EnvTypes>::Balance;
}
impl Env for SrmlEnv {
fn caller() -> Vec<u8> {
unsafe { c_abi::ext_caller() };
let size = unsafe { c_abi::ext_scratch_size() };
impl<T> Env for SrmlEnv<T>
where
T: EnvTypes,
<T as EnvTypes>::Address: for<'a> From<&'a [u8]>,
{
fn caller() -> <Self as EnvTypes>::Address {
unsafe { sys::ext_caller() };
let size = unsafe { sys::ext_scratch_size() };
let mut value = Vec::new();
if size > 0 {
value.resize(size as usize, 0);
unsafe {
c_abi::ext_scratch_copy(value.as_mut_ptr() as u32, 0, size);
sys::ext_scratch_copy(value.as_mut_ptr() as u32, 0, size);
}
}
value
value.as_slice().into()
}
unsafe fn store(key: Key, value: &[u8]) {
c_abi::ext_set_storage(
sys::ext_set_storage(
key.as_bytes().as_ptr() as u32,
1,
value.as_ptr() as u32,
......@@ -88,39 +85,39 @@ impl Env for SrmlEnv {
}
unsafe fn clear(key: Key) {
c_abi::ext_set_storage(key.as_bytes().as_ptr() as u32, 0, 0, 0)
sys::ext_set_storage(key.as_bytes().as_ptr() as u32, 0, 0, 0)
}
unsafe fn load(key: Key) -> Option<Vec<u8>> {
const SUCCESS: u32 = 0;
let result = c_abi::ext_get_storage(key.as_bytes().as_ptr() as u32);
let result = sys::ext_get_storage(key.as_bytes().as_ptr() as u32);
if result != SUCCESS {
return None
}
let size = c_abi::ext_scratch_size();
let size = sys::ext_scratch_size();
let mut value = Vec::new();
if size > 0 {
value.resize(size as usize, 0);
c_abi::ext_scratch_copy(value.as_mut_ptr() as u32, 0, size);
sys::ext_scratch_copy(value.as_mut_ptr() as u32, 0, size);
}
Some(value)
}
fn input() -> Vec<u8> {
let size = unsafe { c_abi::ext_input_size() };
let size = unsafe { sys::ext_input_size() };
if size == 0 {
Vec::new()
} else {
let mut buffer = Vec::new();
buffer.resize(size as usize, 0);
unsafe { c_abi::ext_input_copy(buffer.as_mut_ptr() as u32, 0, size); }
unsafe { sys::ext_input_copy(buffer.as_mut_ptr() as u32, 0, size); }
buffer
}
}
fn return_(data: &[u8]) -> ! {
unsafe {
c_abi::ext_return(data.as_ptr() as u32, data.len() as u32);
sys::ext_return(data.as_ptr() as u32, data.len() as u32);
}
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of pDSL.
//
// pDSL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// pDSL is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with pDSL. If not, see <http://www.gnu.org/licenses/>.
#[cfg(not(feature = "test-env"))]
mod sys;
#[cfg(not(feature = "test-env"))]
mod env;
mod types;
pub use self::{
types::{
Address,
Balance,
},
};
#[cfg(not(feature = "test-env"))]
pub use self::{
env::{SrmlEnv, DefaultSrmlEnv, DefaultSrmlTypes},
};
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of pDSL.
//
// pDSL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// pDSL is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with pDSL. If not, see <http://www.gnu.org/licenses/>.
//! External C API to communicate with substrate contracts runtime module.
//!
//! Refer to substrate SRML contract module for more documentation.
extern "C" {
// Currently unused due to rework of SRML contracts internals. (PUT_CODE)
#[allow(unused)]
pub fn ext_create(
init_code_ptr: u32,
init_code_len: u32,
gas: u64,
value_ptr: u32,
value_len: u32,
input_data_ptr: u32,
input_data_len: u32
) -> u32;
// Currently unused due to rework of SRML contracts internals. (PUT_CODE)
#[allow(unused)]
pub fn ext_call(
callee_ptr: u32,
callee_len: u32,
gas: u64,
value_ptr: u32,
value_len: u32,
input_data_ptr: u32,
input_data_len: u32
) -> u32;
pub fn ext_caller();
pub fn ext_set_storage(
key_ptr: u32,
value_non_null: u32,
value_ptr: u32,
value_len: u32
);
pub fn ext_get_storage(key_ptr: u32) -> u32;
pub fn ext_scratch_size() -> u32;
pub fn ext_scratch_copy(dest_ptr: u32, offset: u32, len: u32);
pub fn ext_input_size() -> u32;
pub fn ext_input_copy(dest_ptr: u32, offset: u32, len: u32);
pub fn ext_return(data_ptr: u32, data_len: u32) -> !;
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of pDSL.
//
// pDSL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// pDSL is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with pDSL. If not, see <http://www.gnu.org/licenses/>.
use parity_codec::{Encode, Decode};
/// The default SRML address type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
pub struct Address([u8; 32]);
impl<'a> From<&'a [u8]> for Address {
fn from(bytes: &'a [u8]) -> Self {
assert_eq!(bytes.len(), 32);
let mut array = [0; 32];
let bytes = &bytes[..array.len()]; // panics if not enough data
array.copy_from_slice(bytes);
Address(array)
}
}
/// The default SRML balance type.
pub type Balance = u64;
......@@ -17,7 +17,10 @@
use super::*;
use core::cell::{Cell, RefCell};
use crate::memory::collections::hash_map::{HashMap, Entry};
use crate::{
env::srml,
memory::collections::hash_map::{HashMap, Entry},
};
/// An entry in the storage of the test environment.
///
......@@ -196,8 +199,8 @@ impl TestEnvData {
const FAILURE: i32 = -1;
/// Returns the caller of the contract invocation.
pub fn caller(&self) -> Vec<u8> {
self.caller.clone()
pub fn caller(&self) -> srml::Address {
srml::Address::from(self.caller.as_slice())
}
/// Stores the given value under the given key in the contract storage.
......@@ -327,8 +330,16 @@ impl TestEnv {
const TEST_ENV_LOG_TARGET: &'static str = "test-env";
impl Env for TestEnv {
fn caller() -> Vec<u8> {
impl EnvTypes for TestEnv {
type Address = srml::Address;
type Balance = srml::Balance;
}
impl Env for TestEnv
where
<Self as EnvTypes>::Address: for<'a> From<&'a [u8]>
{
fn caller() -> <Self as EnvTypes>::Address {
log::debug!(
target: TEST_ENV_LOG_TARGET,
"TestEnv::caller()"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment