From 20645bbdd2652daf732919a24023dd13618d5797 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Wed, 5 Jun 2024 12:06:51 +0300 Subject: [PATCH 1/3] custome proxy via sc.config --- framework/derive/src/generate/abi_gen.rs | 1 + framework/derive/src/model/method.rs | 1 + .../src/contract/generate_proxy/proxy_generator.rs | 8 ++++++-- .../meta-lib/src/contract/sc_config/sc_config_proxy.rs | 5 +++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/framework/derive/src/generate/abi_gen.rs b/framework/derive/src/generate/abi_gen.rs index 5d5a73934c..16dc5179b7 100644 --- a/framework/derive/src/generate/abi_gen.rs +++ b/framework/derive/src/generate/abi_gen.rs @@ -50,6 +50,7 @@ fn generate_endpoint_snippet( }; let label_names = &m.label_names; + // let custome_proxy = &m.custome_proxy; let mutability_tokens = mutability.to_tokens(); let endpoint_type_tokens = endpoint_type.to_tokens(); diff --git a/framework/derive/src/model/method.rs b/framework/derive/src/model/method.rs index 776e39dfaa..a69dbffeed 100644 --- a/framework/derive/src/model/method.rs +++ b/framework/derive/src/model/method.rs @@ -41,6 +41,7 @@ pub struct Method { pub method_args: Vec, pub output_names: Vec, pub label_names: Vec, + // pub custome_proxy: Vec, pub return_type: syn::ReturnType, pub implementation: MethodImpl, } diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs index d2e0b22036..8da3e4d9e8 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs @@ -144,7 +144,7 @@ where } if !self.contract_abi.endpoints.is_empty() { - self.write_endpoints(); + self.write_endpoints(&self.proxy_config.custome_proxy_endpoints); } } @@ -210,11 +210,15 @@ where self.writeln("}"); } - fn write_endpoints(&mut self) { + fn write_endpoints(&mut self, custome_endpoints: &[String]) { let endpoints: Vec = self.contract_abi.endpoints.clone(); self.write_header_impl_endpoints(); for (i, endpoint_abi) in endpoints.into_iter().enumerate() { + if !custome_endpoints.is_empty() && !custome_endpoints.contains(&endpoint_abi.name) { + continue; + } + if i > 0 { self.writeln(""); } diff --git a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs index 88721fe6e7..1ee15e1229 100644 --- a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs +++ b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs @@ -18,6 +18,10 @@ pub struct ProxyConfigSerde { #[serde(default)] pub variant: Option, + + #[serde(default)] + #[serde(rename = "custome-endpoints")] + pub custome_proxy_endpoints: Vec, } impl ProxyConfigSerde { @@ -27,6 +31,7 @@ impl ProxyConfigSerde { override_import: None, path_rename: None, variant: None, + custome_proxy_endpoints: Vec::new(), } } } From dc40d4c22e37f17755af14373bc7f4caed829211 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Wed, 5 Jun 2024 16:46:14 +0300 Subject: [PATCH 2/3] custom proxy via attr --- .../basic-features/sc-config.toml | 6 ++++++ .../src/basic_features_proxy.rs | 10 +++++++++ .../basic-features/src/egld_decimal.rs | 1 + .../src/storage_direct_store.rs | 1 + framework/base/src/abi/endpoint_abi.rs | 3 +++ framework/base/src/external_view_contract.rs | 1 + framework/derive/src/generate/abi_gen.rs | 9 ++++++-- framework/derive/src/model/argument.rs | 1 + framework/derive/src/model/endpoint.rs | 2 ++ framework/derive/src/model/method.rs | 13 +++++++++++- .../derive/src/parse/attributes/attr_names.rs | 1 + .../src/parse/attributes/endpoint_attr.rs | 4 ++++ framework/derive/src/parse/endpoint_parse.rs | 21 +++++++++++++++++-- framework/derive/src/parse/method_parse.rs | 13 +++++++----- .../generate_proxy/proxy_generator.rs | 18 +++++++++++++--- .../src/contract/sc_config/sc_config_proxy.rs | 6 +++--- .../scenario/tests/contract_without_macros.rs | 4 ++++ 17 files changed, 98 insertions(+), 16 deletions(-) diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index c870fda7cb..ceab0b2221 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -8,3 +8,9 @@ overflow-checks = true # needed for overflow tests add-unlabelled = false add-endpoints = ["init", "load_bytes", "store_bytes"] kill_legacy_callback = true + +[[proxy]] +path = "src/basic_features_proxy.rs" +custom-endpoints = [ + "load_bytes" +] \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/src/basic_features_proxy.rs b/contracts/feature-tests/basic-features/src/basic_features_proxy.rs index 7131607d8c..a24485d6ca 100644 --- a/contracts/feature-tests/basic-features/src/basic_features_proxy.rs +++ b/contracts/feature-tests/basic-features/src/basic_features_proxy.rs @@ -1,3 +1,12 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + use multiversx_sc::proxy_imports::*; pub struct BasicFeaturesProxy; @@ -53,6 +62,7 @@ where To: TxTo, Gas: TxGas, { + pub fn load_bytes( self, ) -> TxTypedCall> { diff --git a/contracts/feature-tests/basic-features/src/egld_decimal.rs b/contracts/feature-tests/basic-features/src/egld_decimal.rs index 0b27ed84c6..8c630e641d 100644 --- a/contracts/feature-tests/basic-features/src/egld_decimal.rs +++ b/contracts/feature-tests/basic-features/src/egld_decimal.rs @@ -3,6 +3,7 @@ multiversx_sc::imports!(); /// Used for testing the egld_decimal function return type #[multiversx_sc::module] pub trait EgldDecimal { + #[custom_proxy] #[payable("EGLD")] #[endpoint] fn returns_egld_decimal(&self) -> ManagedDecimal> { diff --git a/contracts/feature-tests/basic-features/src/storage_direct_store.rs b/contracts/feature-tests/basic-features/src/storage_direct_store.rs index 337af9c19a..47915433b1 100644 --- a/contracts/feature-tests/basic-features/src/storage_direct_store.rs +++ b/contracts/feature-tests/basic-features/src/storage_direct_store.rs @@ -5,6 +5,7 @@ use crate::types::*; /// Storage tests: direct store. #[multiversx_sc::module] pub trait StorageStoreFeatures { + #[custom_proxy] #[endpoint] #[storage_set("storage_bytes")] fn store_bytes(&self, bi: ManagedBuffer); diff --git a/framework/base/src/abi/endpoint_abi.rs b/framework/base/src/abi/endpoint_abi.rs index 03e098d0e9..44e6fc64d7 100644 --- a/framework/base/src/abi/endpoint_abi.rs +++ b/framework/base/src/abi/endpoint_abi.rs @@ -51,6 +51,7 @@ pub struct EndpointAbi { pub inputs: Vec, pub outputs: OutputAbis, pub allow_multiple_var_args: bool, + pub custom_proxy: bool, } impl EndpointAbi { @@ -69,6 +70,7 @@ impl EndpointAbi { payable_in_tokens: &[&str], labels: &[&str], allow_multiple_var_args: bool, + custom_proxy: bool, ) -> Self { EndpointAbi { docs: docs.iter().map(|s| s.to_string()).collect(), @@ -83,6 +85,7 @@ impl EndpointAbi { inputs: Vec::new(), outputs: Vec::new(), allow_multiple_var_args, + custom_proxy, } } diff --git a/framework/base/src/external_view_contract.rs b/framework/base/src/external_view_contract.rs index 2b01176176..e306f3fb96 100644 --- a/framework/base/src/external_view_contract.rs +++ b/framework/base/src/external_view_contract.rs @@ -45,6 +45,7 @@ pub fn external_view_contract_constructor_abi() -> EndpointAbi { EndpointTypeAbi::Init, &[], &[], + false, false ); endpoint_abi.inputs.push(InputAbi { diff --git a/framework/derive/src/generate/abi_gen.rs b/framework/derive/src/generate/abi_gen.rs index 16dc5179b7..db186d567a 100644 --- a/framework/derive/src/generate/abi_gen.rs +++ b/framework/derive/src/generate/abi_gen.rs @@ -4,6 +4,7 @@ use crate::model::{ PublicRole, }; +#[allow(clippy::too_many_arguments)] fn generate_endpoint_snippet( m: &Method, endpoint_name: &str, @@ -12,6 +13,7 @@ fn generate_endpoint_snippet( mutability: EndpointMutabilityMetadata, endpoint_type: EndpointTypeMetadata, allow_multiple_var_args: bool, + custom_proxy: bool, ) -> proc_macro2::TokenStream { let endpoint_docs = &m.docs; let rust_method_name = m.name.to_string(); @@ -50,10 +52,8 @@ fn generate_endpoint_snippet( }; let label_names = &m.label_names; - // let custome_proxy = &m.custome_proxy; let mutability_tokens = mutability.to_tokens(); let endpoint_type_tokens = endpoint_type.to_tokens(); - quote! { let mut endpoint_abi = multiversx_sc::abi::EndpointAbi::new( &[ #(#endpoint_docs),* ], @@ -66,6 +66,7 @@ fn generate_endpoint_snippet( &[ #(#payable_in_tokens),* ], &[ #(#label_names),* ], #allow_multiple_var_args, + #custom_proxy ); #(#input_snippets)* #output_snippet @@ -86,6 +87,7 @@ fn generate_endpoint_snippets(contract: &ContractTrait) -> Vec Vec Vec Vec, + pub custom_proxy: bool, } diff --git a/framework/derive/src/model/endpoint.rs b/framework/derive/src/model/endpoint.rs index 1385dd1ada..2a4cf2fe62 100644 --- a/framework/derive/src/model/endpoint.rs +++ b/framework/derive/src/model/endpoint.rs @@ -15,12 +15,14 @@ pub struct EndpointMetadata { pub only_user_account: bool, pub mutability: EndpointMutabilityMetadata, pub allow_multiple_var_args: bool, + pub custom_proxy: bool, } #[derive(Clone, Debug)] pub struct CallbackMetadata { pub callback_name: syn::Ident, pub allow_multiple_var_args: bool, + pub custom_proxy: bool, } /// Method visibility from the point of view of the smart contract diff --git a/framework/derive/src/model/method.rs b/framework/derive/src/model/method.rs index a69dbffeed..90794479d4 100644 --- a/framework/derive/src/model/method.rs +++ b/framework/derive/src/model/method.rs @@ -41,7 +41,6 @@ pub struct Method { pub method_args: Vec, pub output_names: Vec, pub label_names: Vec, - // pub custome_proxy: Vec, pub return_type: syn::ReturnType, pub implementation: MethodImpl, } @@ -99,6 +98,18 @@ impl Method { } } + pub fn is_custom_proxy(&self) -> bool { + match &self.public_role { + PublicRole::Init(_init_metadata) => false, + PublicRole::Upgrade(_upgrade_metadata) => false, + PublicRole::Endpoint(endpoint_metadata) => endpoint_metadata.custom_proxy, + PublicRole::Callback(callback_metadata) + | PublicRole::CallbackPromise(callback_metadata) => callback_metadata.custom_proxy, + PublicRole::CallbackRaw => false, + PublicRole::Private => false, + } + } + pub fn is_allow_multiple_var_args(&self) -> bool { match &self.public_role { PublicRole::Init(init_metadata) => init_metadata.allow_multiple_var_args, diff --git a/framework/derive/src/parse/attributes/attr_names.rs b/framework/derive/src/parse/attributes/attr_names.rs index 8df56f06f6..22a96cf644 100644 --- a/framework/derive/src/parse/attributes/attr_names.rs +++ b/framework/derive/src/parse/attributes/attr_names.rs @@ -27,3 +27,4 @@ pub(super) static ATTR_PROXY: &str = "proxy"; pub(super) static ATTR_LABEL: &str = "label"; pub(super) static ATTR_ALLOW_MULTIPLE_VAR_ARGS: &str = "allow_multiple_var_args"; pub(super) static ATTR_UPGRADE: &str = "upgrade"; +pub(super) static ATTR_CUSTOM_PROXY: &str = "custom_proxy"; diff --git a/framework/derive/src/parse/attributes/endpoint_attr.rs b/framework/derive/src/parse/attributes/endpoint_attr.rs index 678675b202..06890cca4b 100644 --- a/framework/derive/src/parse/attributes/endpoint_attr.rs +++ b/framework/derive/src/parse/attributes/endpoint_attr.rs @@ -32,6 +32,10 @@ pub fn is_upgrade(attr: &syn::Attribute) -> bool { is_attribute_with_no_args(attr, ATTR_UPGRADE) } +pub fn is_custom_proxy(attr: &syn::Attribute) -> bool { + is_attribute_with_no_args(attr, ATTR_CUSTOM_PROXY) +} + #[derive(Clone, Debug)] pub struct EndpointAttribute { pub endpoint_name: Option, diff --git a/framework/derive/src/parse/endpoint_parse.rs b/framework/derive/src/parse/endpoint_parse.rs index 5edc30ad08..7eb36c036c 100644 --- a/framework/derive/src/parse/endpoint_parse.rs +++ b/framework/derive/src/parse/endpoint_parse.rs @@ -5,8 +5,8 @@ use crate::model::{ use super::{ attributes::{ - is_allow_multiple_var_args, is_callback_raw, is_init, is_only_admin, is_only_owner, - is_only_user_account, is_upgrade, CallbackAttribute, EndpointAttribute, + is_allow_multiple_var_args, is_callback_raw, is_custom_proxy, is_init, is_only_admin, + is_only_owner, is_only_user_account, is_upgrade, CallbackAttribute, EndpointAttribute, ExternalViewAttribute, LabelAttribute, OutputNameAttribute, PromisesCallbackAttribute, ViewAttribute, }, @@ -66,6 +66,18 @@ pub fn process_allow_multiple_var_args_attribute( is_allow_multiple_var_args } +pub fn process_custom_proxy_attribute( + attr: &syn::Attribute, + pass_1_data: &mut MethodAttributesPass1, +) -> bool { + let is_custom_proxy = is_custom_proxy(attr); + if is_custom_proxy { + pass_1_data.custom_proxy = true; + } + + is_custom_proxy +} + pub fn process_only_owner_attribute( attr: &syn::Attribute, pass_1_data: &mut MethodAttributesPass1, @@ -119,6 +131,7 @@ pub fn process_endpoint_attribute( only_user_account: pass_1_data.only_user_account, mutability: EndpointMutabilityMetadata::Mutable, allow_multiple_var_args: pass_1_data.allow_multiple_var_args, + custom_proxy: pass_1_data.custom_proxy, }); }) .is_some() @@ -144,6 +157,7 @@ pub fn process_view_attribute( only_user_account: pass_1_data.only_user_account, mutability: EndpointMutabilityMetadata::Readonly, allow_multiple_var_args: pass_1_data.allow_multiple_var_args, + custom_proxy: pass_1_data.custom_proxy, }); }) .is_some() @@ -169,6 +183,7 @@ pub fn process_external_view_attribute( only_user_account: pass_1_data.only_user_account, mutability: EndpointMutabilityMetadata::Readonly, allow_multiple_var_args: pass_1_data.allow_multiple_var_args, + custom_proxy: pass_1_data.custom_proxy, }); }) .is_some() @@ -195,6 +210,7 @@ pub fn process_callback_attribute(attr: &syn::Attribute, method: &mut Method) -> method.public_role = PublicRole::Callback(CallbackMetadata { callback_name: callback_ident, allow_multiple_var_args: method.is_allow_multiple_var_args(), + custom_proxy: method.is_custom_proxy(), }); }) .is_some() @@ -211,6 +227,7 @@ pub fn process_promises_callback_attribute(attr: &syn::Attribute, method: &mut M method.public_role = PublicRole::CallbackPromise(CallbackMetadata { callback_name: callback_ident, allow_multiple_var_args: method.is_allow_multiple_var_args(), + custom_proxy: method.is_custom_proxy(), }); }) .is_some() diff --git a/framework/derive/src/parse/method_parse.rs b/framework/derive/src/parse/method_parse.rs index a8c8a111c7..49ddb77637 100644 --- a/framework/derive/src/parse/method_parse.rs +++ b/framework/derive/src/parse/method_parse.rs @@ -8,11 +8,11 @@ use super::{ process_storage_mapper_attribute, process_storage_set_attribute, }, extract_method_args, process_allow_multiple_var_args_attribute, process_callback_attribute, - process_callback_raw_attribute, process_endpoint_attribute, process_external_view_attribute, - process_init_attribute, process_label_names_attribute, process_only_admin_attribute, - process_only_owner_attribute, process_only_user_account_attribute, - process_output_names_attribute, process_payable_attribute, process_promises_callback_attribute, - process_upgrade_attribute, process_view_attribute, + process_callback_raw_attribute, process_custom_proxy_attribute, process_endpoint_attribute, + process_external_view_attribute, process_init_attribute, process_label_names_attribute, + process_only_admin_attribute, process_only_owner_attribute, + process_only_user_account_attribute, process_output_names_attribute, process_payable_attribute, + process_promises_callback_attribute, process_upgrade_attribute, process_view_attribute, }; pub struct MethodAttributesPass1 { pub method_name: String, @@ -21,6 +21,7 @@ pub struct MethodAttributesPass1 { pub only_admin: bool, pub only_user_account: bool, pub allow_multiple_var_args: bool, + pub custom_proxy: bool, } pub fn process_method(m: &syn::TraitItemFn, trait_attributes: &TraitProperties) -> Method { @@ -39,6 +40,7 @@ pub fn process_method(m: &syn::TraitItemFn, trait_attributes: &TraitProperties) only_admin: trait_attributes.only_admin, only_user_account: trait_attributes.only_user_account, allow_multiple_var_args: trait_attributes.allow_multiple_var_args, + custom_proxy: trait_attributes.custom_proxy, }; let mut first_pass_unprocessed_attributes = Vec::new(); @@ -94,6 +96,7 @@ fn process_attribute_first_pass( || process_only_admin_attribute(attr, first_pass_data) || process_only_user_account_attribute(attr, first_pass_data) || process_allow_multiple_var_args_attribute(attr, first_pass_data) + || process_custom_proxy_attribute(attr, first_pass_data) } fn process_attributes_second_pass( diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs index 8da3e4d9e8..3d9069ca80 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs @@ -143,9 +143,21 @@ where self.write_upgrades(); } + let custom_endpoints = self.collect_custom_endpoints(); + if !self.contract_abi.endpoints.is_empty() { - self.write_endpoints(&self.proxy_config.custome_proxy_endpoints); + self.write_endpoints(&custom_endpoints); + } + } + + fn collect_custom_endpoints(&mut self) -> Vec { + let mut custom_endpoints = self.proxy_config.custom_proxy_endpoints.clone(); + for endpoint_abi in self.contract_abi.endpoints.clone() { + if endpoint_abi.custom_proxy && !custom_endpoints.contains(&endpoint_abi.name) { + custom_endpoints.push(endpoint_abi.name) + } } + custom_endpoints } fn write_types(&mut self) { @@ -210,12 +222,12 @@ where self.writeln("}"); } - fn write_endpoints(&mut self, custome_endpoints: &[String]) { + fn write_endpoints(&mut self, custom_endpoints: &[String]) { let endpoints: Vec = self.contract_abi.endpoints.clone(); self.write_header_impl_endpoints(); for (i, endpoint_abi) in endpoints.into_iter().enumerate() { - if !custome_endpoints.is_empty() && !custome_endpoints.contains(&endpoint_abi.name) { + if !custom_endpoints.is_empty() && !custom_endpoints.contains(&endpoint_abi.name) { continue; } diff --git a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs index 1ee15e1229..49eb58cced 100644 --- a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs +++ b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs @@ -20,8 +20,8 @@ pub struct ProxyConfigSerde { pub variant: Option, #[serde(default)] - #[serde(rename = "custome-endpoints")] - pub custome_proxy_endpoints: Vec, + #[serde(rename = "custom-endpoints")] + pub custom_proxy_endpoints: Vec, } impl ProxyConfigSerde { @@ -31,7 +31,7 @@ impl ProxyConfigSerde { override_import: None, path_rename: None, variant: None, - custome_proxy_endpoints: Vec::new(), + custom_proxy_endpoints: Vec::new(), } } } diff --git a/framework/scenario/tests/contract_without_macros.rs b/framework/scenario/tests/contract_without_macros.rs index 1121e88fdd..783ca5cdfc 100644 --- a/framework/scenario/tests/contract_without_macros.rs +++ b/framework/scenario/tests/contract_without_macros.rs @@ -397,6 +397,7 @@ mod sample_adder { &[], &[], false, + false, ); endpoint_abi .add_output::< @@ -418,6 +419,7 @@ mod sample_adder { &[], &[], false, + false, ); endpoint_abi.add_input::>("initial_value"); contract_abi.add_type_descriptions::>(); @@ -433,6 +435,7 @@ mod sample_adder { &[], &[], false, + false, ); endpoint_abi.add_input::>("initial_value"); contract_abi.add_type_descriptions::>(); @@ -448,6 +451,7 @@ mod sample_adder { &[], &[], false, + false, ); endpoint_abi.add_input::>("value"); contract_abi.add_type_descriptions::>(); From fc36f87d19a870a807fe09588cc8e9b9ca1f0e06 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Wed, 5 Jun 2024 16:47:30 +0300 Subject: [PATCH 3/3] fix typo --- .../meta-lib/src/contract/generate_proxy/proxy_generator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs index 3d9069ca80..65d2641275 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs @@ -534,7 +534,7 @@ where let processed_rust_type = process_rust_type(rust_type.to_string(), paths, processed_paths); - self.rename_path_with_custome_config(&processed_rust_type) + self.rename_path_with_custom_config(&processed_rust_type) } fn start_write_type( @@ -589,7 +589,7 @@ where self.writeln(" }"); } - fn rename_path_with_custome_config(&self, processed_type: &str) -> String { + fn rename_path_with_custom_config(&self, processed_type: &str) -> String { let mut renamed_processed_type = processed_type.to_owned(); if let Some(paths_rename) = &self.proxy_config.path_rename {