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

Enable ink_metadata to be used for metadata generation outside of ink! #1357

Merged
merged 26 commits into from
Nov 2, 2022

Conversation

xermicus
Copy link
Contributor

@xermicus xermicus commented Aug 17, 2022

In order to fix this issue together with this change, we want to enable metadata construction at runtime. In Solang, we'd like to rely on the official ink! crates instead of maintaining our own solution. Additionally, it will be useful for anyone attempting to produce metadata for substrate contracts outside cargo-contract (e.g. when other languages want to add a Substrate target).

So far, this PR:

  • Adds new constructors where needed
  • Opens up some builder to be generic over Form
  • Makes String the default String type

Ideally this should not break any existing API.

@xermicus xermicus changed the title switch API to support String Enable ink_metadata to be used for metadata generation outside of ink! Aug 29, 2022
@xermicus xermicus marked this pull request as ready for review August 29, 2022 16:46
@@ -397,19 +428,19 @@ pub struct MessageSpec<F: Form = MetaForm> {
///
/// In case of trait provided messages and constructors the prefix
/// by convention in ink! is the label of the trait.
label: F::String,
pub label: F::String,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't forget to remove all these pub modifiers to require use of builders

Copy link
Contributor Author

Choose a reason for hiding this comment

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

almost forgot 🐒 thanks!

Copy link
Contributor Author

@xermicus xermicus Oct 27, 2022

Choose a reason for hiding this comment

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

#[must_use] is set for the new<T>(ty: T) function, however there is no other means to construct it anyways? There is no builder for ReturnTypeSpec (probably because there is only one fuild anyways). So I just moved the must_use to the ReturnTypeSpec itself

@codecov-commenter
Copy link

codecov-commenter commented Oct 27, 2022

Codecov Report

Merging #1357 (f7556d6) into master (4825d0b) will increase coverage by 19.38%.
The diff coverage is 52.27%.

❗ Current head f7556d6 differs from pull request most recent head c658c46. Consider uploading reports for the commit c658c46 to get more accurate results

@@             Coverage Diff             @@
##           master    #1357       +/-   ##
===========================================
+ Coverage   44.77%   64.16%   +19.38%     
===========================================
  Files         200      200               
  Lines        6101     6111       +10     
===========================================
+ Hits         2732     3921     +1189     
+ Misses       3369     2190     -1179     
Impacted Files Coverage Δ
crates/metadata/src/lib.rs 0.00% <0.00%> (ø)
crates/metadata/src/utils.rs 50.00% <37.50%> (-20.00%) ⬇️
crates/metadata/src/specs.rs 69.30% <56.52%> (-4.66%) ⬇️
crates/metadata/src/layout/mod.rs 75.63% <100.00%> (ø)
crates/allocator/src/bump.rs 86.55% <0.00%> (-0.85%) ⬇️
crates/e2e/src/lib.rs 0.00% <0.00%> (ø)
crates/e2e/src/xts.rs 0.00% <0.00%> (ø)
crates/env/src/engine/off_chain/test_api.rs 64.70% <0.00%> (+5.88%) ⬆️
crates/ink/ir/src/ir/selector.rs 80.00% <0.00%> (+8.00%) ⬆️
... and 33 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Copy link
Contributor

@SkymanOne SkymanOne left a comment

Choose a reason for hiding this comment

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

LGTM

} else {
item.trim_end()
pub trait DocString {
fn trim_extra_whitespace(item: Self) -> Self;
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Add docs with examples

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got rid of it completely 😁

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.

Constructors need to be tidied up a bit.

Since this will part of ink 4.0, we are not constrained here by having to make the changes non breaking as we were with scale-info so a bit more flexibility.

@@ -730,7 +800,7 @@ where

/// The 4 byte selector to identify constructors and messages
#[derive(Debug, Default, PartialEq, Eq, derive_more::From)]
pub struct Selector([u8; 4]);
pub struct Selector(pub [u8; 4]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is the pub still needed now with the new constructor?

@@ -511,7 +519,7 @@ impl FieldLayout {
/// Creates a new field layout.
pub fn new<N, L>(name: N, layout: L) -> Self
where
N: Into<&'static str>,
N: Into<<MetaForm as Form>::String>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should just use this constructor and make it generic over form, and remove new_custom below

@@ -241,6 +247,10 @@ where
pub fn ty(&self) -> &F::Type {
&self.ty
}

pub fn new_from_ty(key: LayoutKey, ty: <F as Form>::Type) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this constructor should become new because it allows setting all fields. The existing new<T> can be renamed to from_key<T> or similar to be consistent.

@@ -525,6 +533,17 @@ impl<F> FieldLayout<F>
where
F: Form,
{
/// Creates a new custom field layout.
pub fn new_custom<N, L>(name: N, layout: L) -> Self
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 in favour of generic new constructor

@@ -942,6 +1024,21 @@ impl<F> EventParamSpec<F>
where
F: Form,
{
/// Creates a new event paramater specification builder from a custom type.
pub fn new_custom(label: F::String, ty: TypeSpec<F>) -> EventParamSpecBuilder<F> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

EventParamSpecBuilder already has of_type to mutate the type, so you don't need this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason for it was that Type::new() is currently only implemented for MetaForm, but this should be doable

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes we should open up any idiomatic new constructors to be generic

@@ -1102,6 +1208,15 @@ impl<F> MessageParamSpec<F>
where
F: Form,
{
/// Constructs a new message parameter specification via builder.
pub fn new_custom(label: F::String, ty: TypeSpec<F>) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can then remove this and use MessageParamSpecBuilder::of_type

@@ -366,21 +393,25 @@ impl<S, P> ConstructorSpecBuilder<S, P> {
/// Sets the documentation of the message specification.
pub fn docs<D>(self, docs: D) -> Self
where
D: IntoIterator<Item = &'static str>,
D: IntoIterator<Item = <F as Form>::String>,
F::String: DocString,
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
F::String: DocString,
F::String: AsRef<[u8]>,

This might work to avoid requiring the DocString trait and the new impls.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Neat idea!

{
let mut this = self;
debug_assert!(this.spec.docs.is_empty());
this.spec.docs = docs
.into_iter()
.map(trim_extra_whitespace)
.map(DocString::trim_extra_whitespace)
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
.map(DocString::trim_extra_whitespace)
.map(|s| trim_extra_whitespace(s.as_ref()))

Then you should be able to do something like this.

@@ -888,6 +966,10 @@ where
pub fn display_name(&self) -> &DisplayName<F> {
&self.display_name
}

pub fn new_from_ty(ty: <F as Form>::Type, display_name: DisplayName<F>) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again I would make this the new constructor, and change the existing new<T> to e.g. of_type<T> or maybe with_type<T> as other constructors are called on this.

@@ -58,11 +58,26 @@ where
deserializer.deserialize_str(Visitor)
}

/// Strips a single whitespace at the start and removes trailing spaces
pub fn trim_extra_whitespace(item: &str) -> &str {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This might be able to be restored and remove the duplicate impls, see usage site above with AsRef<[u8]> bound

Copy link
Contributor Author

@xermicus xermicus Nov 2, 2022

Choose a reason for hiding this comment

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

The ÀsRef<[u8]>` part is not even needed, was able to nail it using just str refs 👌

@xermicus
Copy link
Contributor Author

xermicus commented Nov 2, 2022

@ascjones was able to tidy this up quite a bit and got rid of all the new_customs and new_with_tys etc. I think I'm done implementing all your code review suggestions, thanks! ❤️ Only downside is I had to break the API (just slightly) so I'm gonna wait for the CI, but I think you can glance over the code again already if you feel like it

@ascjones
Copy link
Collaborator

ascjones commented Nov 2, 2022

Only downside is I had to break the API (just slightly)

Breaking the API here is totally fine since this will be part of a major release 4.0 anyway.

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 just needs CI fixing

@ascjones
Copy link
Collaborator

ascjones commented Nov 2, 2022

LGTM just needs CI fixing

Oh it's a subxt thing, I will look at that now

@xermicus
Copy link
Contributor Author

xermicus commented Nov 2, 2022

Yeah right the CI failures seem unrelated to the change. Just got to watch as TypeSpec::new is now TypeSpec::of_type

@xermicus
Copy link
Contributor Author

xermicus commented Nov 2, 2022

LGTM just needs CI fixing

Oh it's a subxt thing, I will look at that now

Do you want me to wait with merging?

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.

contract-transcoder for non-ink projects
4 participants