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

Basic support for dyn Trait to allow cross-contract calls only with trait #1673

Merged
merged 15 commits into from
Mar 3, 2023

Conversation

xgreenx
Copy link
Collaborator

@xgreenx xgreenx commented Feb 22, 2023

The change uses the ideas from the issue. But instead of #[ink(dyn)] proc macro, it uses the contract_ref! macro rule.

The difference between those approaches is that with contract_ref!, we cover all possible use cases of the usage but don't have the highlighting and hinting in the IDEs. While with #[ink(dyn)], we would have basic highlighting for methods from the trait in the IDEs, the usage will be specific and limited by the number of supported syntax constructions.

The contract_ref! doesn't block us from adding #[ink(dyn)] in the future. We can have both because they use the exact mechanism under the hood.

  • Added contract_ref! macro rule that allows creating a wrapper around the trait defined via #[ink::trait_definition].
  • Added From<AccountId> for the contract builder and forwarder to simplify the usage.
  • Added AsRef<AccountId> and AsMut<AccountId> for builder, forwarder, and contract_ref to provide the way modify the wrapper.

…nd the trait defined via `#[ink::trait_definition]`.

Added `From<AccountId>` for the contract builder and forwarder to simplify the usage.
Added `AsRev<AccountId>` and `AsMut<AccountId>` for builder, forwarder, and contract_ref to provide the way modify the wrapper.
@@ -132,6 +132,18 @@ impl CallBuilder<'_> {
<AccountId as ::core::clone::Clone>::clone(&self.account_id)
}
}

impl ::core::convert::AsRef<AccountId> for #cb_ident {
Copy link

@deuszx deuszx Feb 23, 2023

Choose a reason for hiding this comment

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

<3 such a small change and so much less code on my side :)

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.

Very nice.

Just the question mark of whether we need the $env arg on the contract_ref! macro.

crates/ink/src/contract_ref.rs Show resolved Hide resolved
@@ -0,0 +1,106 @@
#![cfg_attr(not(feature = "std"), no_std)]

/// We can't run E2E test without the contract. So add `Dummy` contract.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this the same issue as #1672

Copy link
Collaborator Author

@xgreenx xgreenx Feb 23, 2023

Choose a reason for hiding this comment

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

No, it is another reason. During running of the cargo test --features e2e-tests ink! tries to build the crate as a contract via cargo-contract. But if it is not a contract, it will fail because it doesn't have ___ink_generate_metadata function=)

Copy link
Collaborator

Choose a reason for hiding this comment

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

That seems like a bug, we shouldn't need the metadata anymore for ink_e2e

Copy link
Collaborator

Choose a reason for hiding this comment

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

Anyway we should attempt to make this more ergonomic for structuring e2e tests in this way

Copy link
Collaborator

Choose a reason for hiding this comment

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

This prompted me to open #1683 which means it doesn't need to generate the metadata anymore.

Not sure it will make this structure work without the dummy contract, but at least it is an immprovement.

Copy link
Collaborator

Choose a reason for hiding this comment

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

See #1691 for a possible solution

…tract`.

Added more examples into documentation
@xgreenx xgreenx requested review from ascjones and removed request for cmichi, HCastano and SkymanOne February 24, 2023 10:26
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.

LGTM

Copy link
Contributor

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

Nice, less code that I would've expected to get something working 💪

I still want to look through the E2E tests a bit more, so I'll do that tomorrow

Comment on lines 98 to 100
///
/// If someone wants to use another type than [`AccountId`] in the [`Environment::AccountId`],
/// he should implement this trait for the corresponding type.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why should this be an option? Doesn't that circumvent the whole point of the trait?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We can add the trait AccountIdGuard as a constraint for the Environment::AccountId, but in this case, it will be breaking change=) But we will force users to implement it

Copy link
Contributor

Choose a reason for hiding this comment

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

That doesn't really answer my question though. Why would a user want to implement this for a type other an AccountId?

If we don't want this, but don't want to introduce a breaking change, then we shouldn't be highlighting the fact that they can implement this trait on other types

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The user wants to implement it if he uses another type for the Environment::AccountId than ink::types::AccountId.

We want this, because it will give the From<AccountId> implementation to the user. If it is not a problem to add constrain for Environment::AccountId, I prefer to add it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay I see what you mean now. I'm gonna update the comment to make this more clear

Copy link
Contributor

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

Couples questions around the integration tests

integration-tests/trait-dyn-cross-contract-calls/lib.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Show resolved Hide resolved
integration-tests/trait-dyn-cross-contract-calls/lib.rs Outdated Show resolved Hide resolved
integration-tests/trait-dyn-cross-contract-calls/lib.rs Outdated Show resolved Hide resolved
Comment on lines 98 to 100
///
/// If someone wants to use another type than [`AccountId`] in the [`Environment::AccountId`],
/// he should implement this trait for the corresponding type.
Copy link
Contributor

Choose a reason for hiding this comment

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

That doesn't really answer my question though. Why would a user want to implement this for a type other an AccountId?

If we don't want this, but don't want to introduce a breaking change, then we shouldn't be highlighting the fact that they can implement this trait on other types

xgreenx and others added 3 commits March 2, 2023 18:46
Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Copy link
Contributor

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

Cool, thanks 💪

@HCastano
Copy link
Contributor

HCastano commented Mar 3, 2023

@cmichi wants to take a look at this as well, so let's not ape this in just yet

@cmichi
Copy link
Collaborator

cmichi commented Mar 3, 2023

Please don't merge just yet, I'll take a look this morning as well.

@deuszx
Copy link

deuszx commented Mar 3, 2023

Normally, when working with Rust, dyn Trait are discouraged due to dynamic dispatching that affects the performance. Are there any implications for Wasm programs that use dyn Traits? Is there anything unusual b/c we're interpreting the contracts (wasmi)?

@xgreenx
Copy link
Collaborator Author

xgreenx commented Mar 3, 2023

Normally, when working with Rust, dyn Trait are discouraged due to dynamic dispatching that affects the performance.

With dynamic dispatching, the compiler is unable to optimize the code, and at runtime, it requires additional steps to find the function to execute.

Are there any implications for Wasm programs that use dyn Traits? Is there anything unusual b/c we're interpreting the contracts (wasmi)?

The program will work as usual. Only that can affect the size of the final contract. It may be more or less than without dynamic dispatching(It is based on several factors).

BTW, the current solution doesn't use dynamic dispatching=) it is called dyn Trait, but the truth is that we use the type that implements the Trait trait.

Copy link
Collaborator

@cmichi cmichi left a comment

Choose a reason for hiding this comment

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

Thank you, Green! Just some doc nitpicks.

crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
crates/ink/src/contract_ref.rs Outdated Show resolved Hide resolved
Co-authored-by: Michael Müller <mich@elmueller.net>
@cmichi
Copy link
Collaborator

cmichi commented Mar 3, 2023

Oh and Green, CHANGELOG.md entry would be great.

@cmichi cmichi merged commit f5f3ebe into use-ink:master Mar 3, 2023
ascjones pushed a commit that referenced this pull request Mar 3, 2023
… trait (#1673)

* Added `contract_ref!` macro rule that allows to create a wrapper around the trait defined via `#[ink::trait_definition]`.
Added `From<AccountId>` for the contract builder and forwarder to simplify the usage.
Added `AsRev<AccountId>` and `AsMut<AccountId>` for builder, forwarder, and contract_ref to provide the way modify the wrapper.

* Added comments for the method in the example of the `contract_ref!`

* Make clippy happy

* Make CI happy

* Changed the default behaviour to use alias generated by the `ink::contract`.
Added more examples into documentation

* Apply suggestions from code review

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>

* Apply comments from the PR

* Missed the comment

* Remove error from the example

* Apply suggestions from code review

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>

* Fixed comments from PR

* Update comments around `AccountIdGuard`

* Apply suggestions from code review

Co-authored-by: Michael Müller <mich@elmueller.net>

* Mentioned the PR in the `Unreleased` section

---------

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Co-authored-by: Hernando Castano <hernando@hcastano.com>
Co-authored-by: Michael Müller <mich@elmueller.net>
@SkymanOne SkymanOne mentioned this pull request Mar 23, 2023
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.

5 participants