Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Rewrite define_env! as a procedural macro #11344

Closed
athei opened this issue May 3, 2022 · 5 comments · Fixed by #11888
Closed

Rewrite define_env! as a procedural macro #11344

athei opened this issue May 3, 2022 · 5 comments · Fixed by #11888
Assignees
Labels
Z2-medium Can be fixed by a coder with good Rust knowledge but little knowledge of the codebase.

Comments

@athei
Copy link
Member

athei commented May 3, 2022

Currently, the contracts pallet uses the define_env! macro by example in order to define which host functions are available for contracts.

This macro should be rewritten as a procedural attribute macro in order to achieve the following benefits:

  • Easier to maintain macro code
  • Better syntax for defining metadata of host functions (the module name for example) as attributes
  • rustfmt support
  • Make the host functions visible in rustdoc by emitting some public mock type

There is already a pallet-contracts-proc-macro crate where this macro could live.

@athei athei added the Z2-medium Can be fixed by a coder with good Rust knowledge but little knowledge of the codebase. label May 3, 2022
@athei athei assigned agryaznov and unassigned achimcc Jun 21, 2022
@agryaznov
Copy link
Contributor

agryaznov commented Jul 20, 2022

So the new way we define the env (in wasm/runtime.rs) would be as follows:

#[define_env]
pub mod env {
	#[host("seal0")]
	fn gas(ctx: Runtime<E: Ext>, amount: u32) {
		ctx.charge_gas(RuntimeCosts::MeteringBlock(amount))?;
		Ok(())
	}

	#[host("seal1")]
	fn seal_set_storage(ctx: Runtime<E: Ext>, key_ptr: u32, value_ptr: u32, value_len: u32) -> u32 {
		ctx.set_storage(KeyType::Fix, key_ptr, value_ptr, value_len)
	}
...
}

@athei wdyt?

@athei
Copy link
Member Author

athei commented Jul 21, 2022

Looks good in general. I have the following suggestions

  1. Don't require a special attribute to flag something as host function. Everything in this module is a host function implicitly. So it won't get polluted with other stuff.
  2. Let's don't allow setting the module manually. Add a numeric version so we can do some arithmetic on it when necessary.
  3. Added #[prefixed_alias] just as an example for a new attribute. Should be a follow up PR.
#[define_env]
pub mod env {
        // implicit version 0, no prefixing required as this function is only called "gas"
	fn gas(ctx: Runtime<E: Ext>, amount: u32);

       // implicit version 0, add alias "seal_set_storage"
       #[prefixed_alias]
	fn set_storage(ctx: Runtime<E: Ext>, key_ptr: u32, value_ptr: u32, value_len: u32);

        // new version of function. also need alias
	#[version(1)]
        #[prefixed_alias]
	fn set_storage(ctx: Runtime<E: Ext>, key_ptr: u32, value_ptr: u32, value_len: u32) -> u32 ;
       
       // implicit version 0, no prefix required as newly added function
       fn crazy_new_function();
}

@agryaznov
Copy link
Contributor

agryaznov commented Jul 22, 2022

  1. Added #[prefixed_alias] just as an example for a new attribute. Should be a follow up PR.

This one delayed for now for a follow-up PR.

Applying all other suggestions, here is how environment definition will look like (in wasm/runtime.rs):

#[define_env(Env)]
pub mod env {
        // will be expanded to the "seal0" module 
	fn gas(ctx: Runtime<E: Ext>, amount: u32) {
		ctx.charge_gas(RuntimeCosts::MeteringBlock(amount))?;
		Ok(())
	}

        // will be expanded to the "seal0" module 
	fn seal_set_storage(ctx: Runtime<E: Ext>, key_ptr: u32, value_ptr: u32, value_len: u32) {
		ctx.set_storage(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
	}

        // will be expanded to the "seal1" module 
	#[version(1)]
	fn seal_set_storage(ctx: Runtime<E: Ext>, key_ptr: u32, value_ptr: u32, value_len: u32) -> u32 {
		ctx.set_storage(KeyType::Fix, key_ptr, value_ptr, value_len)
	}

        // will be expanded to the "__unstable__" module 
	#[unstable]
	fn seal_set_storage(
		ctx: Runtime<E: Ext>,
		key_ptr: u32,
		key_len: u32,
		value_ptr: u32,
		value_len: u32,
	) -> u32 {
		ctx.set_storage(KeyType::Variable(key_len), key_ptr, value_ptr, value_len)
	}
}
...

@athei
Copy link
Member Author

athei commented Jul 22, 2022

Cool but let's not make one letter attributes :) : v -> version.

@agryaznov
Copy link
Contributor

Ok. Also added attribute for the environment identifier, like #[define_env(Env)] or #[define_env(Test)]

@athei athei moved this to In Progress in Smart Contracts Jul 27, 2022
Repository owner moved this from In Progress 🛠 to Done ✅ in Smart Contracts Aug 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Z2-medium Can be fixed by a coder with good Rust knowledge but little knowledge of the codebase.
Projects
Status: No status
Development

Successfully merging a pull request may close this issue.

3 participants