mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 02:57:57 +00:00
contracts: Don't put unstable functions in special module (#12781)
* Don't put unstable functions in special module * Apply suggestions from code review Co-authored-by: Sasha Gryaznov <hi@agryaznov.com> * cargo fmt Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
This commit is contained in:
committed by
GitHub
parent
c5ce79a439
commit
0068716b5a
@@ -157,6 +157,7 @@ struct HostFn {
|
||||
module: String,
|
||||
name: String,
|
||||
returns: HostFnReturn,
|
||||
is_unstable: bool,
|
||||
}
|
||||
|
||||
enum HostFnReturn {
|
||||
@@ -191,27 +192,34 @@ impl HostFn {
|
||||
};
|
||||
|
||||
// process attributes
|
||||
let msg = "only #[version(<u8>)] or #[unstable] attribute is allowed.";
|
||||
let msg =
|
||||
"only #[version(<u8>)], #[unstable] and #[prefixed_alias] attributes are allowed.";
|
||||
let span = item.span();
|
||||
let mut attrs = item.attrs.clone();
|
||||
attrs.retain(|a| !(a.path.is_ident("doc") || a.path.is_ident("prefixed_alias")));
|
||||
let name = item.sig.ident.to_string();
|
||||
let module = match attrs.len() {
|
||||
0 => Ok("seal0".to_string()),
|
||||
1 => {
|
||||
let attr = &attrs[0];
|
||||
let ident = attr.path.get_ident().ok_or(err(span, msg))?.to_string();
|
||||
match ident.as_str() {
|
||||
"version" => {
|
||||
let ver: syn::LitInt = attr.parse_args()?;
|
||||
Ok(format!("seal{}", ver.base10_parse::<u8>().map_err(|_| err(span, msg))?))
|
||||
},
|
||||
"unstable" => Ok("__unstable__".to_string()),
|
||||
_ => Err(err(span, msg)),
|
||||
}
|
||||
},
|
||||
_ => Err(err(span, msg)),
|
||||
}?;
|
||||
let mut maybe_module = None;
|
||||
let mut is_unstable = false;
|
||||
while let Some(attr) = attrs.pop() {
|
||||
let ident = attr.path.get_ident().ok_or(err(span, msg))?.to_string();
|
||||
match ident.as_str() {
|
||||
"version" => {
|
||||
if maybe_module.is_some() {
|
||||
return Err(err(span, "#[version] can only be specified once"))
|
||||
}
|
||||
let ver: u8 =
|
||||
attr.parse_args::<syn::LitInt>().and_then(|lit| lit.base10_parse())?;
|
||||
maybe_module = Some(format!("seal{}", ver));
|
||||
},
|
||||
"unstable" => {
|
||||
if is_unstable {
|
||||
return Err(err(span, "#[unstable] can only be specified once"))
|
||||
}
|
||||
is_unstable = true;
|
||||
},
|
||||
_ => return Err(err(span, msg)),
|
||||
}
|
||||
}
|
||||
|
||||
// process arguments: The first and second arg are treated differently (ctx, memory)
|
||||
// they must exist and be `ctx: _` and `memory: _`.
|
||||
@@ -299,7 +307,13 @@ impl HostFn {
|
||||
_ => Err(err(arg1.span(), &msg)),
|
||||
}?;
|
||||
|
||||
Ok(Self { item, module, name, returns })
|
||||
Ok(Self {
|
||||
item,
|
||||
module: maybe_module.unwrap_or_else(|| "seal0".to_string()),
|
||||
name,
|
||||
returns,
|
||||
is_unstable,
|
||||
})
|
||||
},
|
||||
_ => Err(err(span, &msg)),
|
||||
}
|
||||
@@ -423,9 +437,9 @@ fn expand_functions(
|
||||
f.returns.to_wasm_sig(),
|
||||
&f.item.sig.output
|
||||
);
|
||||
let unstable_feat = match module.as_str() {
|
||||
"__unstable__" => quote! { #[cfg(feature = "unstable-interface")] },
|
||||
_ => quote! {},
|
||||
let unstable_feat = match f.is_unstable {
|
||||
true => quote! { #[cfg(feature = "unstable-interface")] },
|
||||
false => quote! {},
|
||||
};
|
||||
|
||||
// If we don't expand blocks (implementing for `()`) we change a few things:
|
||||
@@ -496,13 +510,15 @@ fn expand_functions(
|
||||
/// ```nocompile
|
||||
/// #[define_env]
|
||||
/// pub mod some_env {
|
||||
/// fn some_host_fn(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<(), TrapReason> {
|
||||
/// fn foo(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<(), TrapReason> {
|
||||
/// ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// This example will expand to the `some_host_fn()` defined in the wasm module named `seal0`.
|
||||
/// To define a host function in `seal1` and `__unstable__` modules, it should be annotated with the
|
||||
/// This example will expand to the `foo()` defined in the wasm module named `seal0`. This is
|
||||
/// because the module `seal0` is the default when no module is specified.
|
||||
///
|
||||
/// To define a host function in `seal2` and `seal3` modules, it should be annotated with the
|
||||
/// appropriate attribute as follows:
|
||||
///
|
||||
/// ## Example
|
||||
@@ -510,17 +526,20 @@ fn expand_functions(
|
||||
/// ```nocompile
|
||||
/// #[define_env]
|
||||
/// pub mod some_env {
|
||||
/// #[version(1)]
|
||||
/// fn some_host_fn(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<ReturnCode, TrapReason> {
|
||||
/// #[version(2)]
|
||||
/// fn foo(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<ReturnCode, TrapReason> {
|
||||
/// ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
|
||||
/// }
|
||||
///
|
||||
/// #[version(3)]
|
||||
/// #[unstable]
|
||||
/// fn some_host_fn(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<u32, TrapReason> {
|
||||
/// fn bar(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<u32, TrapReason> {
|
||||
/// ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// The function `bar` is additionally annotated with `unstable` which removes it from the stable
|
||||
/// interface. Check out the README to learn about unstable functions.
|
||||
///
|
||||
/// In legacy versions of pallet_contracts, it was a naming convention that all host functions had
|
||||
/// to be named with the `seal_` prefix. For the sake of backwards compatibility, each host function
|
||||
@@ -534,21 +553,21 @@ fn expand_functions(
|
||||
/// pub mod some_env {
|
||||
/// #[version(1)]
|
||||
/// #[prefixed_alias]
|
||||
/// fn some_host_fn(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<ReturnCode, TrapReason> {
|
||||
/// fn foo(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<ReturnCode, TrapReason> {
|
||||
/// ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
|
||||
/// }
|
||||
///
|
||||
/// #[unstable]
|
||||
/// fn some_host_fn(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<u32, TrapReason> {
|
||||
/// #[version(42)]
|
||||
/// fn bar(ctx: _, memory: _, key_ptr: u32, value_ptr: u32, value_len: u32) -> Result<u32, TrapReason> {
|
||||
/// ctx.some_host_fn(KeyType::Fix, key_ptr, value_ptr, value_len).map(|_| ())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// In this example, the following host functions will be generated by the macro:
|
||||
/// - `some_host_fn()` in module `seal1`,
|
||||
/// - `seal_some_host_fn()` in module `seal1`,
|
||||
/// - `some_host_fn()` in module `__unstable__`.
|
||||
/// - `foo()` in module `seal1`,
|
||||
/// - `seal_foo()` in module `seal1`,
|
||||
/// - `bar()` in module `seal42`.
|
||||
///
|
||||
/// Only following return types are allowed for the host functions defined with the macro:
|
||||
/// - `Result<(), TrapReason>`,
|
||||
|
||||
Reference in New Issue
Block a user