Unverified Commit ecd609d5 authored by Hero Bird's avatar Hero Bird Committed by GitHub

[core] ext_call PR followup and refinements (#171)

* [core] ext_call PR followup and refinements

* [core] add call_invoke and call_evaluate to api.rs

* [core] extract call method (#172)
parent 1228905c
......@@ -17,6 +17,7 @@
use super::ContractEnvStorage;
use crate::{
env::{
CallError,
traits::{
Env,
EnvTypes,
......@@ -26,7 +27,7 @@ use crate::{
memory::vec::Vec,
storage::Key,
};
use scale::Encode;
use scale::{Encode, Decode};
/// Stores the given value under the specified key in the contract storage.
///
......@@ -84,3 +85,36 @@ where
{
T::dispatch_raw_call(&call.into().encode()[..])
}
/// Invokes a remote smart contract.
///
/// Does not expect to receive return data back.
/// Use this whenever you call a remote smart contract that returns nothing back.
pub fn call_invoke<T>(
callee: T::AccountId,
gas: u64,
value: T::Balance,
input_data: &[u8],
) -> Result<(), CallError>
where
T: Env,
{
T::call_invoke(callee, gas, value, input_data)
}
/// Evaluates a remote smart contract.
///
/// Expects to receive return data back.
/// Use this whenever calling a remote smart contract that returns a value.
pub fn call_evaluate<T, R>(
callee: T::AccountId,
gas: u64,
value: T::Balance,
input_data: &[u8],
) -> Result<R, CallError>
where
T: Env,
R: Decode,
{
T::call_evaluate(callee, gas, value, input_data)
}
......@@ -114,6 +114,32 @@ macro_rules! impl_getters_for_srml_env {
}
}
impl<T> SrmlEnv<T>
where
T: EnvTypes,
{
fn call(
callee: <Self as EnvTypes>::AccountId,
gas: u64,
value: <Self as EnvTypes>::Balance,
input_data: &[u8],
) -> u32 {
let callee = callee.encode();
let value = value.encode();
unsafe {
sys::ext_call(
callee.as_ptr() as u32,
callee.len() as u32,
gas,
value.as_ptr() as u32,
value.len() as u32,
input_data.as_ptr() as u32,
input_data.len() as u32,
)
}
}
}
impl<T> Env for SrmlEnv<T>
where
T: EnvTypes,
......@@ -171,24 +197,11 @@ where
value: <Self as EnvTypes>::Balance,
input_data: &[u8],
) -> Result<(), CallError> {
let callee = callee.encode();
let value = value.encode();
unsafe {
let success = sys::ext_call(
callee.as_ptr() as u32,
callee.len() as u32,
gas,
value.as_ptr() as u32,
value.len() as u32,
input_data.as_ptr() as u32,
input_data.len() as u32,
);
if success == 0 {
Ok(())
} else {
Err(CallError)
}
let result = Self::call(callee, gas, value, input_data);
if result != 0 {
return Err(CallError)
}
Ok(())
}
fn call_evaluate<U: Decode>(
......@@ -197,23 +210,10 @@ where
value: <Self as EnvTypes>::Balance,
input_data: &[u8],
) -> Result<U, CallError> {
let callee = callee.encode();
let value = value.encode();
unsafe {
let success = sys::ext_call(
callee.as_ptr() as u32,
callee.len() as u32,
gas,
value.as_ptr() as u32,
value.len() as u32,
input_data.as_ptr() as u32,
input_data.len() as u32,
);
if success == 0 {
U::decode(&mut &read_scratch_buffer()[..]).map_err(|_| CallError)
} else {
Err(CallError)
}
let result = Self::call(callee, gas, value, input_data);
if result != 0 {
return Err(CallError)
}
U::decode(&mut &read_scratch_buffer()[..]).map_err(|_| CallError)
}
}
......@@ -32,6 +32,8 @@ extern "C" {
) -> u32;
/// Calls a remote smart contract.
///
/// Eventually returned data is put into the scratch buffer.
pub fn ext_call(
callee_ptr: u32,
callee_len: u32,
......
......@@ -61,7 +61,7 @@ pub struct RawCallData {
/// Decoded call data of recorded external calls.
pub struct CallData<E>
where
E: crate::env::EnvTypes,
E: EnvTypes,
{
pub callee: E::AccountId,
pub gas: u64,
......@@ -196,7 +196,7 @@ pub struct TestEnvData {
/// The total transferred value.
value_transferred: Vec<u8>,
/// The recorded external calls.
calls: Vec<CallData>,
calls: Vec<RawCallData>,
/// The expected return data of the next external call.
call_return: Vec<u8>,
/// Returned data.
......@@ -341,7 +341,7 @@ impl TestEnvData {
/// Records a new external call.
pub fn add_call(&mut self, callee: &[u8], gas: u64, value: &[u8], input_data: &[u8]) {
let new_call = CallData {
let new_call = RawCallData {
callee: callee.to_vec(),
gas,
value: value.to_vec(),
......@@ -350,6 +350,16 @@ impl TestEnvData {
self.calls.push(new_call);
}
/// Returns an iterator over all recorded external calls.
pub fn external_calls(&self) -> impl DoubleEndedIterator<Item = &RawCallData> {
self.calls.iter()
}
/// Set the expected return data of the next external call.
pub fn set_return_data(&mut self, return_data: &[u8]) {
self.return_data = return_data.to_vec();
}
/// Returns the latest returned data.
pub fn returned_data(&self) -> &[u8] {
&self.return_data
......@@ -501,6 +511,12 @@ where
.with(|test_env| test_env.borrow_mut().set_input(input_bytes.to_vec()))
}
/// Sets the expected return data for the next external call.
pub fn set_return_data(expected_return_data: &[u8]) {
TEST_ENV_DATA
.with(|test_env| test_env.borrow_mut().set_return_data(expected_return_data))
}
impl_env_setters_for_test_env!(
(set_address, address, T::AccountId),
(set_balance, balance, T::Balance),
......@@ -522,6 +538,27 @@ where
})
}
/// Returns an iterator over all emitted events.
pub fn external_calls() -> impl DoubleEndedIterator<Item = CallData<T>> {
TEST_ENV_DATA.with(|test_env| {
test_env
.borrow()
.external_calls()
.map(|raw_call_data| {
CallData {
callee: Decode::decode(&mut &raw_call_data.callee[..])
.expect("invalid encoded callee"),
gas: raw_call_data.gas,
value: Decode::decode(&mut &raw_call_data.value[..])
.expect("invalid encoded value"),
input_data: raw_call_data.input_data.clone(),
}
})
.collect::<Vec<_>>()
.into_iter()
})
}
/// Returns an iterator over all dispatched calls.
pub fn dispatched_calls() -> impl DoubleEndedIterator<Item = T::Call> {
TEST_ENV_DATA.with(|test_env| {
......
Markdown is supported
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