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

Environment agnostic contract invocation API #2219

Merged
merged 37 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
fca4e05
WIP ideas
ascjones Apr 8, 2024
840aa43
Add invocation
ascjones Apr 11, 2024
9c88b33
SP
ascjones Apr 11, 2024
e12d262
Warnings
ascjones Apr 11, 2024
081d718
WIP add info trait
ascjones Apr 16, 2024
6b500cf
Revert "WIP add info trait"
ascjones Apr 16, 2024
667ad39
WIP TraitCallBuilder
ascjones Apr 19, 2024
08da1a0
Revert "WIP TraitCallBuilder"
ascjones Apr 19, 2024
95b8591
Generate and wire up TraitMessageBuilder
ascjones Apr 19, 2024
56ce1a7
trait impl
ascjones Apr 22, 2024
ebde85d
Utilize message builder from call builder
ascjones Apr 22, 2024
19b4dca
Use type inference
ascjones Apr 22, 2024
53eb64d
Try to use new API...
ascjones Apr 22, 2024
d9ed700
Add storage deposit limit
ascjones Apr 23, 2024
cf1b94f
Add sandbox err message
ascjones Apr 23, 2024
bf06c85
Revert "Add sandbox err message"
ascjones Apr 23, 2024
9174a14
message_builder!
ascjones Apr 23, 2024
d198e6b
Invoker Error type
ascjones Apr 23, 2024
1a09074
Invoker -> Executor
ascjones Apr 23, 2024
e0a6d5e
Extract executor to separate file
ascjones Apr 24, 2024
ce6cbbe
Merge branch 'master' into aj/hybrid-ink-api
ascjones Apr 24, 2024
80d5f27
Access TraitCallBuilder from as-dependency call builder
ascjones Apr 24, 2024
a3f21ba
docs
ascjones Apr 24, 2024
054d415
executor ref and move message_builder to own file + docs
ascjones Apr 25, 2024
ae430f7
executor ref and move message_builder to own file + docs
ascjones Apr 25, 2024
574c253
remove message_builder
ascjones Apr 25, 2024
35e633d
message_builder docs
ascjones Apr 25, 2024
6f4022a
fix message_builder doc tests
ascjones Apr 25, 2024
2bacee0
remove conflicting message builder impl
ascjones Apr 25, 2024
0c9480b
fmt
ascjones Apr 25, 2024
75811af
UI tests
ascjones Apr 25, 2024
8753ded
docs
ascjones Apr 25, 2024
12e01c1
Merge branch 'master' into aj/hybrid-ink-api
ascjones Apr 25, 2024
caa0fce
update copypasta comments
ascjones Apr 25, 2024
0aea636
Merge branch 'master' into aj/hybrid-ink-api
ascjones Apr 26, 2024
a34849c
license headers
ascjones Apr 26, 2024
aa9e29f
CHANGELOG.md
ascjones Apr 26, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- [Linter] Add links to detailed lint description ‒ [#2170](https://github.com/use-ink/ink/pull/2170)
- Environment agnostic contract invocation API ‒ [#219](https://github.com/use-ink/ink/pull/2219)

### Changed
- [E2E] Update `subxt` and `polkadot-sdk` dependencies ‒ [#2174](https://github.com/use-ink/ink/pull/2174)
Expand Down
22 changes: 22 additions & 0 deletions crates/env/src/call/call_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{
Set,
Unset,
},
Execution,
ExecutionInput,
},
types::Gas,
Expand Down Expand Up @@ -513,6 +514,27 @@ where
_phantom: PhantomData<fn() -> E>,
}

impl<E, Args, RetType> From<Execution<Args, RetType>>
for CallBuilder<
E,
Unset<Call<E>>,
Set<ExecutionInput<Args>>,
Set<ReturnType<RetType>>,
>
where
E: Environment,
{
fn from(invoke: Execution<Args, RetType>) -> Self {
CallBuilder {
call_type: Default::default(),
call_flags: CallFlags::empty(),
exec_input: Set(invoke.input),
return_type: Set(invoke.output),
_phantom: Default::default(),
}
}
}

impl<E, CallType, Args, RetType> CallBuilder<E, Unset<CallType>, Args, RetType>
where
E: Environment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,59 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::call::Selector;
use super::{
utils::ReturnType,
Selector,
};
use crate::Environment;

/// The input data and the expected return type of a contract execution.
pub struct Execution<Args, Output> {
/// The input data for initiating a contract execution.
pub input: ExecutionInput<Args>,
/// The type of the expected return value of the contract execution.
pub output: ReturnType<Output>,
}

impl<Args, Output> Execution<Args, Output>
where
Args: scale::Encode,
Output: scale::Decode,
{
/// Construct a new contract execution with the given input data.
pub fn new(input: ExecutionInput<Args>) -> Self {
Self {
input,
output: ReturnType::default(),
}
}

/// Perform the execution of the contract with the given executor.
pub fn exec<I, E>(
self,
executor: &I,
) -> Result<ink_primitives::MessageResult<Output>, I::Error>
where
E: Environment,
I: Executor<E>,
{
executor.exec(&self.input)
}
}

/// Implemented in different environments to perform contract execution.
pub trait Executor<E: Environment> {
/// The type of the error that can be returned during execution.
type Error;
/// Perform the contract execution with the given input data, and return the result.
fn exec<Args, Output>(
&self,
input: &ExecutionInput<Args>,
) -> Result<ink_primitives::MessageResult<Output>, Self::Error>
where
Args: scale::Encode,
Output: scale::Decode;
}

/// The input data for a smart contract execution.
#[derive(Clone, Default, Debug)]
Expand Down
10 changes: 7 additions & 3 deletions crates/env/src/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
mod call_builder;
mod common;
mod create_builder;
mod execution_input;
mod execution;
mod selector;

/// Utility types for the cross-contract calling API.
Expand All @@ -29,7 +29,7 @@ pub mod utils {
Unset,
Unwrap,
},
execution_input::{
execution::{
ArgsList,
Argument,
ArgumentList,
Expand Down Expand Up @@ -58,6 +58,10 @@ pub use self::{
LimitParamsV1,
LimitParamsV2,
},
execution_input::ExecutionInput,
execution::{
Execution,
ExecutionInput,
Executor,
},
selector::Selector,
};
60 changes: 44 additions & 16 deletions crates/ink/codegen/src/generator/trait_def/call_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ impl GenerateCode for CallBuilder<'_> {
let storage_layout_impl = self.generate_storage_layout_impl();
let auxiliary_trait_impls = self.generate_auxiliary_trait_impls();
let to_from_account_id_impls = self.generate_to_from_account_id_impls();
let message_builder_trait_impl = self.generate_message_builder_trait_impl();
let ink_trait_impl = self.generate_ink_trait_impl();
quote! {
#struct_definition
#storage_layout_impl
#auxiliary_trait_impls
#to_from_account_id_impls
#message_builder_trait_impl
#ink_trait_impl
}
}
Expand Down Expand Up @@ -271,6 +273,28 @@ impl CallBuilder<'_> {
)
}

/// Generate the trait implementation for `MessageBuilder` for the ink! trait call
/// builder.
///
/// # Note
///
/// Through the implementation of this trait it is possible to refer to the
/// ink! trait messsage builder that is associated to this ink! trait call builder.
fn generate_message_builder_trait_impl(&self) -> TokenStream2 {
let span = self.trait_def.span();
let call_builder_ident = self.ident();
let message_builder_ident = self.trait_def.message_builder_ident();
quote_spanned!(span=>
/// This trait allows to bridge from the call builder to message builder.
impl<E> ::ink::codegen::TraitMessageBuilder for #call_builder_ident<E>
where
E: ::ink::env::Environment
{
type MessageBuilder = #message_builder_ident<E>;
}
)
}

/// Generates the implementation of the associated ink! trait definition.
///
/// # Note
Expand Down Expand Up @@ -310,10 +334,9 @@ impl CallBuilder<'_> {
/// builder.
fn generate_ink_trait_impl_messages(&self) -> TokenStream2 {
let messages = self.trait_def.trait_def.item().iter_items().filter_map(
|(item, selector)| {
item.filter_map_message().map(|message| {
self.generate_ink_trait_impl_for_message(&message, selector)
})
|(item, _selector)| {
item.filter_map_message()
.map(|message| self.generate_ink_trait_impl_for_message(&message))
},
);
quote! {
Expand All @@ -326,9 +349,9 @@ impl CallBuilder<'_> {
fn generate_ink_trait_impl_for_message(
&self,
message: &ir::InkTraitMessage,
selector: ir::Selector,
) -> TokenStream2 {
let span = message.span();
let trait_ident = self.trait_def.trait_def.item().ident();
let message_ident = message.ident();
let attrs = self
.trait_def
Expand All @@ -340,7 +363,6 @@ impl CallBuilder<'_> {
let output = message.output();
let output_type =
output.map_or_else(|| quote! { () }, |output| quote! { #output });
let selector_bytes = selector.hex_lits();
let input_bindings = generator::input_bindings(message.inputs());
let input_types = generator::input_types(message.inputs());
let arg_list = generator::generate_argument_list(input_types.iter().cloned());
Expand All @@ -362,17 +384,23 @@ impl CallBuilder<'_> {
& #mut_tok self
#( , #input_bindings : #input_types )*
) -> Self::#output_ident {
::ink::env::call::build_call::<Self::Env>()
.call(::ink::ToAccountId::to_account_id(self))
.exec_input(
::ink::env::call::ExecutionInput::new(
::ink::env::call::Selector::new([ #( #selector_bytes ),* ])
<::ink::env::call::CallBuilder<
Self::Env,
::ink::env::call::utils::Unset< ::ink::env::call::Call< Self::Env > >,
::ink::env::call::utils::Set< ::ink::env::call::ExecutionInput<#arg_list> >,
::ink::env::call::utils::Set< ::ink::env::call::utils::ReturnType<#output_type> >,
> as ::core::convert::From::<_>>::from(
<<Self as ::ink::codegen::TraitMessageBuilder>::MessageBuilder as #trait_ident>
::#message_ident(
& #mut_tok <<Self
as ::ink::codegen::TraitMessageBuilder>::MessageBuilder
as ::core::default::Default>::default()
#(
, #input_bindings
)*
)
#(
.push_arg(#input_bindings)
)*
)
.returns::<#output_type>()
)
.call(::ink::ToAccountId::to_account_id(self))
}
)
}
Expand Down
Loading