Skip to content

Implement ext_call in ink! #133

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

Merged
merged 6 commits into from
Aug 16, 2019
Merged

Implement ext_call in ink! #133

merged 6 commits into from
Aug 16, 2019

Conversation

taskooh
Copy link
Contributor

@taskooh taskooh commented Jul 8, 2019

I wanna call another contract in a contract.
Is this the right approach to do that?

Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All in all looks decent.
However, you should note that this is a fairly low-level API to what you want to do.
For ink! we had in mind to support a more high-level approach to solve the underlying problem.
For the high-level parts we also need the low-level parts such as implemented in your PR so if you need it I am fine to merge the PR after some minor improvements (also docs are missing).

Copy link
Contributor Author

@taskooh taskooh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the gas generic type

Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should simply rebase to master, not do a merge commit. I suggest you to rewind and do a simple rebase.

@codecov-io
Copy link

codecov-io commented Jul 23, 2019

Codecov Report

Merging #133 into master will decrease coverage by 0.12%.
The diff coverage is 11.76%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #133      +/-   ##
==========================================
- Coverage   79.54%   79.41%   -0.13%     
==========================================
  Files          67       67              
  Lines        4986     4994       +8     
==========================================
  Hits         3966     3966              
- Misses       1020     1028       +8
Impacted Files Coverage Δ
model/src/exec_env.rs 72.72% <ø> (ø) ⬆️
core/src/env/srml/types.rs 0% <ø> (ø) ⬆️
core/src/env/test_env.rs 37.61% <11.76%> (-3%) ⬇️
model/src/contract.rs 89.28% <0%> (+13.92%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 55fb144...724ebe1. Read the comment docs.

@Robbepop Robbepop changed the title use ext_call in ink! Implement ext_call in ink! Jul 23, 2019
@taskooh
Copy link
Contributor Author

taskooh commented Jul 24, 2019

I implemented ReturnData as trait because implementation of get() differs between srml and test_env
to do this, it was difficult to add generic types to ReturnData itself so i added generic types to the get() function.

@taskooh
Copy link
Contributor Author

taskooh commented Jul 26, 2019

@Robbepop
I rebased from master. is there something missing?

@Robbepop
Copy link
Collaborator

Robbepop commented Jul 26, 2019

Sorry, I forgot to push my latest code review for your PR and was already wondering why you don't react. Let me elaborate a bit more on the idea I stated in a comment above about splitting the ext_call API.


There currently is a problem with the proposed API that ext_call might return data that is to be fetch through the scratch buffer. However, not all calls actually return something. So if you implement an automatic scratch buffer retrieval for potential return data you might end up doing this wasted work.

Also the proposed work around with the additional guard type that you already implemented is not working properly either due to the stated problems with in-between-calls.

The idea to fix this is splitting this API up into two parts:

  • fn ext_call_invoke(..)
    Won't return anything but also won't touch the scratch buffer.
    Users should use this for calls where they either won't use the result or where the call won't return data.
  • #[must_use] fn ext_call_evaluate<T: Decode>(..) -> T
    Always fetches and decodes the data in the scratch buffer after the call has been made.
    Also guarantees that users actually use the return value.

I am sorry for causing more work than necessary but we want to get this right and I think this is the way to go.

@Robbepop Robbepop mentioned this pull request Jul 26, 2019
@Robbepop
Copy link
Collaborator

Please rebase this on current master to fix CI issues.


/// Calls a remote smart contract and return access to scratch buffer
pub fn call_evaluate<U:Decode>(
&self,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: &mut self

@Robbepop
Copy link
Collaborator

Robbepop commented Aug 8, 2019

Hey how is it going with this PR?
Can you please rebase on to master so we can actually merge it as soon as you fixed what I have already mentioned to you?
It would be very nice if we could finally pull this over the finishing line.

@taskooh
Copy link
Contributor Author

taskooh commented Aug 12, 2019

@Robbepop Sorry for being late, i was busy for my job.
I realize that test_env is quite not done.

Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please incorporate my suggestions into your PR and run rustfmt over it - many formatting errors.

) -> Result<(), Self::CallError>;

/// Calls a remote smart contract and return encoded data
#[must_use]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are using Result as return type we can remove this #[must_use] again since Result is #[must_use] on a type level already.

@@ -107,6 +112,8 @@ impl<T> Env for SrmlEnv<T>
where
T: EnvTypes,
{
type CallError = CallError;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not want to introduce an associated type for CallError at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any idea where to implement CallError struct?
I want to use same struct in core/src/env/* and in model/src/exec_env.rs

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since ink_model depends on ink_core just define it in ink_core in ink_core::env and use it from ink_model.

input_data: &[u8],
) -> Result<T,CallError> {
add_call(callee, gas, value, input_data);
unimplemented!();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unimplemented!();

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see why you left it there. The returning of this is a bit more involved.
What I would recommend doing is the following:
Create another field in the test environment data (Vec<u8>) that is settable by the user and that is actually taken upon calling call to decode into the expected T. So upon testing a smart contract using the test environment a tester can completely control it and say what it expects from the outside.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got it!
Also, i need to check error of call. Should i add a field of error flag?
Now it can catch only the decoding error, but cant catch error while executing call.

use ink_utils;
use parity_codec::Encode;

pub trait EncodeSafe{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not idiomatic to do that and confusing. Please find another way to test this functionality. You are free to make limited use of macro_rules! macros in order to provide the functionality of your tests if required.

@Robbepop
Copy link
Collaborator

@taskooh we are about to implement a more elaborate version of this feature.

For this we want to base our work on your PR, however, this requires the last remaining work done by you, otherwise we cannot merge it. We do not want to throw away all the work done by you so far. ;)
It would be nice if you could fix the remaining problems so that we can move on this whole feature.

…xt_call

remove #[allow(unused)] from ext_call()

implment call_invoke and call_evaluate

fix format

call_invoke and call_evaluate returns Return<_,CallError>

fixed
Copy link
Collaborator

@Robbepop Robbepop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please apply my code suggestions and remove the one test file I mentioned.
also it is important that you fix the things I mentioned in your current TestEnvData::call implementation -> it is still calling unimplemented!().
rest looks O.K.

@@ -47,6 +50,15 @@ impl EventData {
}
}

/// Emulates the data given to remote smart contract call instructions.
#[allow(unused)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would you need #[allow(unused)]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errors occurred:

error: field is never used: `callee`
  --> core/src/env/test_env.rs:55:5
   |
55 |     callee: Vec<u8>,
   |     ^^^^^^^^^^^^^^^
   |
note: lint level defined here
  --> core/src/lib.rs:42:2
   |
42 |     unused,
   |     ^^^^^^
   = note: #[deny(dead_code)] implied by #[deny(unused)]

error: field is never used: `gas`
  --> core/src/env/test_env.rs:56:5
   |
56 |     gas: u64,
   |     ^^^^^^^^

error: field is never used: `value`
  --> core/src/env/test_env.rs:57:5
   |
57 |     value: Vec<u8>,
   |     ^^^^^^^^^^^^^^

error: field is never used: `input_data`
  --> core/src/env/test_env.rs:58:5
   |
58 |     input_data: Vec<u8>,
   |     ^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the fields pub so that they are accessible from the outside. ;)

@ascjones ascjones self-requested a review August 15, 2019 17:36
@taskooh
Copy link
Contributor Author

taskooh commented Aug 15, 2019

@Robbepop @ascjones Is the return_data in
https://github.com/paritytech/ink/pull/133/conflicts
same as call_return which I implemented?

@@ -47,6 +50,15 @@ impl EventData {
}
}

/// Emulates the data given to remote smart contract call instructions.
#[allow(unused)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the fields pub so that they are accessible from the outside. ;)

Copy link
Collaborator

@ascjones ascjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general looks good. Though as I say in the comment I would move call_invoke and call_evaluate up to model::EnvHandler

@Robbepop
Copy link
Collaborator

Even though there are some outstanding things to do, we (@ascjones and me) decided that we are going to merge this PR and refine it quickly to base our enhancements on top of it. I hope this is to the interest of you @taskooh . Thank you for your work!

@Robbepop Robbepop merged commit 1228905 into use-ink:master Aug 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants