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

Make crate used in entry_point configurable #2068

Merged
merged 4 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ and this project adheres to
- cosmwasm-vm: Add `secp256r1_verify` and `secp256r1_recover_pubkey` imports for
ECDSA signature verification over secp256r1. ([#1983], [#2057], [#2058])
- cosmwasm-vm: Add metrics for the pinned memory cache ([#2059])
- cosmwasm-derive: The crate used in the expansion can now be renamed ([#2068])

[#1983]: https://github.com/CosmWasm/cosmwasm/pull/1983
[#2057]: https://github.com/CosmWasm/cosmwasm/pull/2057
[#2058]: https://github.com/CosmWasm/cosmwasm/pull/2058
[#2068]: https://github.com/CosmWasm/cosmwasm/pull/2068

### Changed

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/burner/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/crypto-verify/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/cyberpunk/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/empty/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/floaty/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/hackatom/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/ibc-reflect-send/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/ibc-reflect/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/queue/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/reflect/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/staking/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/virus/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ proc-macro = true
default = []

[dependencies]
proc-macro2 = "1.0.79"
quote = "1.0.35"
syn = { version = "2", features = ["full"] }

Expand Down
123 changes: 116 additions & 7 deletions packages/derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::parse_macro_input;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, ToTokens};
use syn::{
parse::{Parse, ParseStream},
parse_quote,
punctuated::Punctuated,
Token,
};

macro_rules! maybe {
($result:expr) => {{
match { $result } {
Ok(val) => val,
Err(err) => return err.into_compile_error(),
}
}};
}

struct Options {
crate_path: syn::Path,
}

impl Default for Options {
fn default() -> Self {
Self {
crate_path: parse_quote!(::cosmwasm_std),
}
}
}

impl Parse for Options {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut ret = Self::default();
let attrs = Punctuated::<syn::MetaNameValue, Token![,]>::parse_terminated(input)?;

for kv in attrs {
if kv.path.is_ident("crate") {
let path_as_string: syn::LitStr = syn::parse2(kv.value.to_token_stream())?;
ret.crate_path = path_as_string.parse()?
} else {
return Err(syn::Error::new_spanned(kv, "Unknown attribute"));

Check warning on line 41 in packages/derive/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

packages/derive/src/lib.rs#L41

Added line #L41 was not covered by tests
}
}

Ok(ret)
}
}

/// This attribute macro generates the boilerplate required to call into the
/// contract-specific logic from the entry-points to the Wasm module.
Expand Down Expand Up @@ -50,9 +94,17 @@
/// where `InstantiateMsg`, `ExecuteMsg`, and `QueryMsg` are contract defined
/// types that implement `DeserializeOwned + JsonSchema`.
#[proc_macro_attribute]
pub fn entry_point(_attr: TokenStream, mut item: TokenStream) -> TokenStream {
pub fn entry_point(
attr: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
entry_point_impl(attr.into(), item.into()).into()
}

fn entry_point_impl(attr: TokenStream, mut item: TokenStream) -> TokenStream {
let cloned = item.clone();
let function = parse_macro_input!(cloned as syn::ItemFn);
let function: syn::ItemFn = maybe!(syn::parse2(cloned));
let Options { crate_path } = maybe!(syn::parse2(attr));

// The first argument is `deps`, the rest is region pointers
let args = function.sig.inputs.len() - 1;
Expand All @@ -68,11 +120,68 @@
mod #wasm_export { // new module to avoid conflict of function name
#[no_mangle]
extern "C" fn #fn_name(#( #decl_args : u32 ),*) -> u32 {
cosmwasm_std::#do_call(&super::#fn_name, #( #call_args ),*)
#crate_path::#do_call(&super::#fn_name, #( #call_args ),*)
}
}
};

item.extend(TokenStream::from(new_code));
item.extend(new_code);
item
}

#[cfg(test)]
mod test {
use proc_macro2::TokenStream;
use quote::quote;

use crate::entry_point_impl;

#[test]
fn default_expansion() {
let code = quote! {
fn instantiate(deps: DepsMut, env: Env) -> Response {
// Logic here
}
};

let actual = entry_point_impl(TokenStream::new(), code);
let expected = quote! {
fn instantiate(deps: DepsMut, env: Env) -> Response { }

#[cfg(target_arch = "wasm32")]
mod __wasm_export_instantiate {
#[no_mangle]
extern "C" fn instantiate(ptr_0: u32) -> u32 {
::cosmwasm_std::do_instantiate(&super::instantiate, ptr_0)
}
}
};

assert_eq!(actual.to_string(), expected.to_string());
}

#[test]
fn renamed_expansion() {
let attribute = quote!(crate = "::my_crate::cw_std");
let code = quote! {
fn instantiate(deps: DepsMut, env: Env) -> Response {
// Logic here
}
};

let actual = entry_point_impl(attribute, code);
let expected = quote! {
fn instantiate(deps: DepsMut, env: Env) -> Response { }

#[cfg(target_arch = "wasm32")]
mod __wasm_export_instantiate {
#[no_mangle]
extern "C" fn instantiate(ptr_0: u32) -> u32 {
::my_crate::cw_std::do_instantiate(&super::instantiate, ptr_0)
}
}
};

assert_eq!(actual.to_string(), expected.to_string());
}
}
Loading