Skip to content

Commit ad40643

Browse files
committed
import ext_call to trait and add function to generate input_data of ext_call
remove #[allow(unused)] from ext_call() implment call_invoke and call_evaluate fix format call_invoke and call_evaluate returns Return<_,CallError> fixed
1 parent f5249f3 commit ad40643

File tree

6 files changed

+255
-4
lines changed

6 files changed

+255
-4
lines changed

core/src/env/srml/srml_only/impls.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ use crate::{
2525
storage::Key,
2626
};
2727
use core::marker::PhantomData;
28-
use scale::Decode;
28+
use scale::{
29+
Decode,
30+
Encode,
31+
};
2932

3033
/// Load the contents of the scratch buffer
3134
fn read_scratch_buffer() -> Vec<u8> {
@@ -69,6 +72,8 @@ impl EnvStorage for SrmlEnvStorage {
6972
}
7073
}
7174

75+
pub struct CallError;
76+
7277
/// The SRML contracts environment.
7378
pub struct SrmlEnv<T>
7479
where
@@ -107,6 +112,8 @@ impl<T> Env for SrmlEnv<T>
107112
where
108113
T: EnvTypes,
109114
{
115+
type CallError = CallError;
116+
110117
fn input() -> Vec<u8> {
111118
read_scratch_buffer()
112119
}
@@ -153,4 +160,56 @@ where
153160
fn dispatch_raw_call(data: &[u8]) {
154161
unsafe { sys::ext_dispatch_call(data.as_ptr() as u32, data.len() as u32) }
155162
}
163+
164+
fn call_invoke(
165+
callee: <Self as EnvTypes>::AccountId,
166+
gas: u64,
167+
value: <Self as EnvTypes>::Balance,
168+
input_data: &[u8],
169+
) -> Result<(), CallError> {
170+
let callee = callee.encode();
171+
let value = value.encode();
172+
unsafe {
173+
let success = sys::ext_call(
174+
callee.as_ptr() as u32,
175+
callee.len() as u32,
176+
gas,
177+
value.as_ptr() as u32,
178+
value.len() as u32,
179+
input_data.as_ptr() as u32,
180+
input_data.len() as u32
181+
);
182+
if success == 0 {
183+
Ok(())
184+
} else {
185+
Err(CallError{})
186+
}
187+
}
188+
}
189+
190+
fn call_evaluate<U: Decode>(
191+
callee: <Self as EnvTypes>::AccountId,
192+
gas: u64,
193+
value: <Self as EnvTypes>::Balance,
194+
input_data: &[u8],
195+
) -> Result<U, CallError> {
196+
let callee = callee.encode();
197+
let value = value.encode();
198+
unsafe {
199+
let success = sys::ext_call(
200+
callee.as_ptr() as u32,
201+
callee.len() as u32,
202+
gas,
203+
value.as_ptr() as u32,
204+
value.len() as u32,
205+
input_data.as_ptr() as u32,
206+
input_data.len() as u32
207+
);
208+
if success == 0 {
209+
Ok(U::decode(&mut &read_scratch_buffer()[..]).unwrap())
210+
} else {
211+
Err(CallError{})
212+
}
213+
}
214+
}
156215
}

core/src/env/srml/srml_only/sys.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ extern "C" {
3232
) -> u32;
3333

3434
/// Calls a remote smart contract.
35-
#[allow(unused)]
3635
pub fn ext_call(
3736
callee_ptr: u32,
3837
callee_len: u32,

core/src/env/test_env.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ impl EventData {
4747
}
4848
}
4949

50+
struct CallData {
51+
calee: Vec<u8>,
52+
gas: u64,
53+
value: Vec<u8>,
54+
input_data: Vec<u8>,
55+
}
56+
5057
/// An entry in the storage of the test environment.
5158
///
5259
/// # Note
@@ -179,6 +186,8 @@ pub struct TestEnvData {
179186
gas_left: Vec<u8>,
180187
/// The total transferred value.
181188
value_transferred: Vec<u8>,
189+
/// The calls.
190+
calls: Vec<CallData>,
182191
}
183192

184193
impl Default for TestEnvData {
@@ -200,6 +209,7 @@ impl Default for TestEnvData {
200209
gas_left: Vec::new(),
201210
value_transferred: Vec::new(),
202211
dispatched_calls: Vec::new(),
212+
calls: Vec::new(),
203213
}
204214
}
205215
}
@@ -220,6 +230,7 @@ impl TestEnvData {
220230
self.total_writes = 0;
221231
self.events.clear();
222232
self.dispatched_calls.clear();
233+
self.calls.clear();
223234
}
224235

225236
/// Increments the total number of reads from the storage.
@@ -317,6 +328,23 @@ impl TestEnvData {
317328
pub fn dispatched_calls(&self) -> impl DoubleEndedIterator<Item = &[u8]> {
318329
self.dispatched_calls.iter().map(Vec::as_slice)
319330
}
331+
332+
/// Appends new call to the end of the bytearray.
333+
pub fn add_call(
334+
&mut self,
335+
callee: &[u8],
336+
gas: u64,
337+
value: &[u8],
338+
input_data: &[u8],
339+
) {
340+
let new_call = CallData {
341+
callee: callee.to_vec(),
342+
gas: u64,
343+
value: value.to_vec(),
344+
input_data: input_data.to_vec(),
345+
};
346+
self.calls.push(new_call);
347+
}
320348
}
321349

322350
impl TestEnvData {
@@ -417,6 +445,18 @@ impl TestEnvData {
417445
pub fn dispatch_call(&mut self, call: &[u8]) {
418446
self.add_dispatched_call(call);
419447
}
448+
449+
pub fn call<T: Decode>(
450+
&mut self,
451+
callee: &[u8],
452+
gas: u64,
453+
value: &[u8],
454+
input_data: &[u8],
455+
) -> Result<T,CallError> {
456+
add_call(callee, gas, value, input_data);
457+
unimplemented!();
458+
}
459+
420460
}
421461

422462
thread_local! {
@@ -567,6 +607,31 @@ where
567607
fn dispatch_raw_call(data: &[u8]) {
568608
TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().dispatch_call(data))
569609
}
610+
611+
fn call_invoke(
612+
callee: T::AccountId,
613+
gas: u64,
614+
value: T::Balance,
615+
input_data: &[u8],
616+
) {
617+
let callee = &(callee.encode())[..];
618+
let value = &(value.encode())[..];
619+
TEST_ENV_DATA
620+
.with(|test_env| test_env.borrow_mut().call(callee, gas, value, input_data));
621+
return Result<(),CallError{}>;
622+
}
623+
624+
fn call_evaluate<U : Decode>(
625+
callee: T::AccountId,
626+
gas: u64,
627+
value: T::Balance,
628+
input_data: &[u8],
629+
) -> Option<U> {
630+
let callee = &(callee.encode())[..];
631+
let value = &(value.encode())[..];
632+
TEST_ENV_DATA
633+
.with(|test_env| test_env.borrow_mut().call(callee, gas, value, input_data))
634+
}
570635
}
571636

572637
pub enum TestEnvStorage {}

core/src/env/traits.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ use crate::{
1818
memory::vec::Vec,
1919
storage::Key,
2020
};
21-
use scale::Codec;
21+
use scale::{
22+
Codec,
23+
Decode,
24+
};
2225

2326
#[cfg(not(feature = "test-env"))]
2427
/// The environmental types usable by contracts defined with ink!.
@@ -85,6 +88,10 @@ pub trait EnvStorage {
8588

8689
/// The environment API usable by contracts defined with pDSL.
8790
pub trait Env: EnvTypes {
91+
92+
/// Error type of remote call;
93+
type CallError;
94+
8895
/// Returns the chain address of the contract.
8996
fn address() -> <Self as EnvTypes>::AccountId;
9097

@@ -136,4 +143,21 @@ pub trait Env: EnvTypes {
136143

137144
/// Dispatches a call into the Runtime.
138145
fn dispatch_raw_call(data: &[u8]);
146+
147+
/// Calls a remote smart contract without returning data
148+
fn call_invoke(
149+
callee: <Self as EnvTypes>::AccountId,
150+
gas: u64,
151+
value: <Self as EnvTypes>::Balance,
152+
input_data: &[u8]
153+
) -> Result<(), Self::CallError>;
154+
155+
/// Calls a remote smart contract and return encoded data
156+
#[must_use]
157+
fn call_evaluate<T: Decode>(
158+
callee: <Self as EnvTypes>::AccountId,
159+
gas: u64,
160+
value: <Self as EnvTypes>::Balance,
161+
input_data: &[u8],
162+
) -> Result<T, Self::CallError>;
139163
}

lang/src/encode_input_data.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use ink_core::memory::vec::Vec;
2+
use ink_utils;
3+
use parity_codec::Encode;
4+
5+
pub trait EncodeSafe{
6+
fn encode_safe(&self) -> Vec<u8>;
7+
}
8+
9+
macro_rules! impl_encode_safe {
10+
($( $one:ty ),*) => { $(
11+
impl EncodeSafe for $one {
12+
fn encode_safe(&self) -> Vec<u8> {
13+
parity_codec::Encode::encode(&self)
14+
}
15+
}
16+
)* }
17+
}
18+
19+
impl_encode_safe!(bool,u16,u32,u64,u128,i8,i16,i32,i64,i128,Vec<u8>);
20+
21+
/// make selector from method name
22+
#[allow(unused)]
23+
fn raw_message_selector(name: &str) -> u32 {
24+
let keccak = ink_utils::hash::keccak256(name.as_bytes());
25+
u32::from_le_bytes([keccak[0], keccak[1], keccak[2], keccak[3]])
26+
}
27+
28+
/// encode to input_data from Box wrapped params
29+
#[allow(unused)]
30+
pub fn gen_input_data(method: &str, params: &[Box<EncodeSafe>]) -> Vec<u8>
31+
where
32+
{
33+
let selector = raw_message_selector(method);
34+
let mut input_data = selector.encode();
35+
for param in params.iter() {
36+
let mut encoded_param = param.encode_safe();
37+
input_data.append(&mut encoded_param);
38+
}
39+
return input_data.encode()
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use super::*;
45+
46+
#[test]
47+
fn message_selectors() {
48+
assert_eq!(raw_message_selector("inc"), 257544423);
49+
assert_eq!(raw_message_selector("get"), 4266279973);
50+
assert_eq!(raw_message_selector("compare"), 363906316);
51+
}
52+
53+
#[test]
54+
fn encode(){
55+
let var:bool = false;
56+
assert_eq!(var.encode(), vec![0]);
57+
58+
let var:bool = true;
59+
assert_eq!(var.encode(), vec![1]);
60+
61+
let var :u32 = 22;
62+
assert_eq!(var.encode(), vec![22,0,0,0]);
63+
64+
let var :u32 = 257544423;
65+
assert_eq!(var.encode(), vec![231, 208, 89, 15]);
66+
67+
let mut vec1 : Vec<u8> = Vec::new(); vec1.push(11);
68+
assert_eq!(vec1.encode(), vec![4,11]);
69+
}
70+
71+
#[test]
72+
fn input_data_works(){
73+
let mut params : Vec<Box<EncodeSafe>> = Vec::new();
74+
params.push(Box::new(true));
75+
params.push(Box::new(12u64));
76+
assert_eq!(gen_input_data("inc",&params),vec![52, 231, 208, 89, 15, 1, 12, 0, 0, 0, 0, 0, 0, 0]);
77+
}
78+
}

model/src/exec_env.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ use ink_core::{
2828
Initialize,
2929
},
3030
};
31-
use scale::Encode as _;
31+
use scale::{
32+
Encode as _,
33+
Decode,
34+
};
3235

3336
/// Provides a safe interface to an environment given a contract state.
3437
pub struct ExecutionEnv<State, Env> {
@@ -190,4 +193,27 @@ impl<T: Env> EnvHandler<T> {
190193
{
191194
T::dispatch_raw_call(call.into().encode().as_slice())
192195
}
196+
197+
/// Calls a remote smart contract without returning data.
198+
pub fn call_invoke(
199+
&mut self,
200+
callee: T::AccountId,
201+
gas: u64,
202+
value: T::Balance,
203+
input_data: &[u8],
204+
) -> Result<(), <T as Env>::CallError> {
205+
T::call_invoke(callee, gas, value, input_data)
206+
}
207+
208+
/// Calls a remote smart contract with returning encoded data.
209+
#[must_use]
210+
pub fn call_evaluate<U:Decode>(
211+
&mut self,
212+
callee: T::AccountId,
213+
gas: u64,
214+
value: T::Balance,
215+
input_data: &[u8],
216+
) -> Result<U, <T as Env>::CallError> {
217+
T::call_evaluate(callee, gas, value, input_data)
218+
}
193219
}

0 commit comments

Comments
 (0)