From 804e72dd8be8498cdbc9cfe7a3eb985b9ded3f1b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 23 May 2024 16:54:54 +0300 Subject: [PATCH 1/2] impl upgrade in scenario env --- .../adder/tests/adder_blackbox_test.rs | 13 ++++ .../src/facade/world_tx/scenario_exec_call.rs | 33 ++++++++++- .../scenario/tx_to_step/tx_to_step_call.rs | 59 ++++++++++++++++++- 3 files changed, 100 insertions(+), 5 deletions(-) diff --git a/contracts/examples/adder/tests/adder_blackbox_test.rs b/contracts/examples/adder/tests/adder_blackbox_test.rs index 73d6fecd5f..9f155c4e3a 100644 --- a/contracts/examples/adder/tests/adder_blackbox_test.rs +++ b/contracts/examples/adder/tests/adder_blackbox_test.rs @@ -63,5 +63,18 @@ fn adder_blackbox() { .check_account(ADDER_ADDRESS) .check_storage("str:sum", "6"); + world + .tx() + .from(OWNER_ADDRESS) + .to(ADDER_ADDRESS) + .typed(adder_proxy::AdderProxy) + .upgrade(100u64) + .code(CODE_PATH) + .run(); + + world + .check_account(ADDER_ADDRESS) + .check_storage("str:sum", "100"); + world.write_scenario_trace("trace1.scen.json"); } diff --git a/framework/scenario/src/facade/world_tx/scenario_exec_call.rs b/framework/scenario/src/facade/world_tx/scenario_exec_call.rs index 42a29ef378..8905c7d14d 100644 --- a/framework/scenario/src/facade/world_tx/scenario_exec_call.rs +++ b/framework/scenario/src/facade/world_tx/scenario_exec_call.rs @@ -1,14 +1,15 @@ use multiversx_sc::{ tuple_util::NestedTupleFlatten, types::{ - heap::H256, FunctionCall, ManagedAddress, ManagedBuffer, RHListExec, Tx, TxBaseWithEnv, - TxEnv, TxEnvMockDeployAddress, TxEnvWithTxHash, TxFromSpecified, TxGas, TxPayment, - TxToSpecified, + heap::H256, Code, FunctionCall, ManagedAddress, ManagedBuffer, NotPayable, RHListExec, Tx, + TxBaseWithEnv, TxEnv, TxEnvMockDeployAddress, TxEnvWithTxHash, TxFromSpecified, TxGas, + TxPayment, TxToSpecified, UpgradeCall, }, }; use crate::{ api::StaticApi, + imports::MxscPath, scenario::tx_to_step::{address_annotated, TxToStep}, scenario_model::{SetStateStep, TxExpect, TxResponse}, ScenarioTxEnv, ScenarioTxRun, ScenarioWorld, @@ -90,6 +91,32 @@ where } } +impl<'w, From, To, RH> ScenarioTxRun + for Tx< + ScenarioEnvExec<'w>, + From, + To, + NotPayable, + (), + UpgradeCall, Code>>, + RH, + > +where + From: TxFromSpecified>, + To: TxToSpecified>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn run(self) -> Self::Returns { + let mut step_wrapper = self.tx_to_step(); + step_wrapper.step.explicit_tx_hash = core::mem::take(&mut step_wrapper.env.data.tx_hash); + step_wrapper.env.world.sc_call(&mut step_wrapper.step); + step_wrapper.process_result() + } +} + impl<'w> TxEnvWithTxHash for ScenarioEnvExec<'w> { fn set_tx_hash(&mut self, tx_hash: H256) { assert!(self.data.tx_hash.is_none(), "tx hash set twice"); diff --git a/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs b/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs index 7daa8ac810..475326eac7 100644 --- a/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs +++ b/framework/scenario/src/scenario/tx_to_step/tx_to_step_call.rs @@ -1,8 +1,13 @@ use multiversx_sc::types::{ - FunctionCall, RHListExec, Tx, TxEnv, TxFromSpecified, TxGas, TxPayment, TxToSpecified, + Code, FunctionCall, NotPayable, RHListExec, Tx, TxEnv, TxFromSpecified, TxGas, TxPayment, + TxToSpecified, UpgradeCall, }; -use crate::scenario_model::{ScCallStep, TxESDT, TxExpect, TxResponse}; +use crate::{ + imports::MxscPath, + scenario_model::{ScCallStep, TxESDT, TxExpect, TxResponse}, + ScenarioEnvExec, +}; use super::{address_annotated, gas_annotated, StepWrapper, TxToStep}; @@ -75,3 +80,53 @@ where step } + +impl<'w, From, To, RH> TxToStep, RH> + for Tx< + ScenarioEnvExec<'w>, + From, + To, + NotPayable, + (), + UpgradeCall, Code>>, + RH, + > +where + From: TxFromSpecified>, + To: TxToSpecified>, + RH: RHListExec>, +{ + type Step = ScCallStep; + + fn tx_to_step(self) -> StepWrapper, Self::Step, RH> { + let mut step = tx_to_sc_call_upgrade_step(&self.env, self.from, self.to, self.data); + step.expect = Some(self.result_handler.list_tx_expect()); + + StepWrapper { + env: self.env, + step, + result_handler: self.result_handler, + } + } +} + +pub fn tx_to_sc_call_upgrade_step<'a, 'w: 'a, From, To>( + env: &'a ScenarioEnvExec<'w>, + from: From, + to: To, + data: UpgradeCall, Code>, +) -> ScCallStep +where + From: TxFromSpecified>, + To: TxToSpecified>, +{ + let mut step = ScCallStep::new() + .from(address_annotated(env, &from)) + .to(address_annotated(env, &to)) + .function("upgrade"); + for arg in data.arg_buffer.iter_buffers() { + step.tx.arguments.push(arg.to_vec().into()); + } + + step +} From 6ed982689bafc2fc6bcedb84008de2f2b928326a Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 23 May 2024 17:05:11 +0300 Subject: [PATCH 2/2] sc-meta all proxy --compare impl --- .github/workflows/proxy-compare.yml | 31 +++++++++++++++++++ .../meta/src/cli_args/cli_args_contract.rs | 22 +++++++++++-- framework/meta/src/cmd/contract.rs | 8 ++++- .../contract/generate_proxy/proxy_gen_main.rs | 27 ++++++++++++++++ .../generate_proxy/proxy_generator.rs | 10 +++--- 5 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/proxy-compare.yml diff --git a/.github/workflows/proxy-compare.yml b/.github/workflows/proxy-compare.yml new file mode 100644 index 0000000000..3eef6460d6 --- /dev/null +++ b/.github/workflows/proxy-compare.yml @@ -0,0 +1,31 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +jobs: + proxy_compare: + name: Proxy compare - newly generated vs present in file tree + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + default: true + toolchain: stable + target: wasm32-unknown-unknown + + - name: Install prerequisites + run: | + cargo install --path framework/meta + + - name: Run proxy compare + run: | + cd contracts + sc-meta all proxy --compare diff --git a/framework/meta/src/cli_args/cli_args_contract.rs b/framework/meta/src/cli_args/cli_args_contract.rs index e05146a9bc..4a7f0ee4c7 100644 --- a/framework/meta/src/cli_args/cli_args_contract.rs +++ b/framework/meta/src/cli_args/cli_args_contract.rs @@ -71,7 +71,7 @@ pub enum ContractCliAction { name = "proxy", about = "Generates a proxy, based on the contract ABI." )] - GenerateProxies, + GenerateProxies(GenerateProxyArgs), } impl CliArgsToRaw for ContractCliAction { @@ -103,8 +103,9 @@ impl CliArgsToRaw for ContractCliAction { raw.push("snippets".to_string()); raw.append(&mut args.to_raw()); }, - ContractCliAction::GenerateProxies => { + ContractCliAction::GenerateProxies(args) => { raw.push("proxy".to_string()); + raw.append(&mut args.to_raw()); }, } raw @@ -127,3 +128,20 @@ impl CliArgsToRaw for GenerateSnippetsArgs { raw } } + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct GenerateProxyArgs { + /// Runs proxy comparison (newly generated vs already present on disk). + #[arg(long, verbatim_doc_comment)] + pub compare: bool, +} + +impl CliArgsToRaw for GenerateProxyArgs { + fn to_raw(&self) -> Vec { + let mut raw = Vec::new(); + if self.compare { + raw.push("--compare".to_string()); + } + raw + } +} diff --git a/framework/meta/src/cmd/contract.rs b/framework/meta/src/cmd/contract.rs index 3e1008a3a3..4076f8393d 100644 --- a/framework/meta/src/cmd/contract.rs +++ b/framework/meta/src/cmd/contract.rs @@ -33,7 +33,13 @@ pub fn cli_main() { meta_config_opt.generate_rust_snippets(&gs_arg); meta_config_opt.generate_proxy() }, - ContractCliAction::GenerateProxies => meta_config_opt.generate_proxy(), + ContractCliAction::GenerateProxies(proxy_args) => { + if proxy_args.compare { + meta_config_opt.compare_proxy() + } else { + meta_config_opt.generate_proxy() + } + }, } } diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs index 0619a65cb5..3529e736b4 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs @@ -1,3 +1,6 @@ +use colored::Colorize; +use std::fs; + use multiversx_sc::abi::ContractAbi; use crate::cmd::contract::sc_config::ProxyConfigSerde; @@ -6,6 +9,8 @@ use super::{ super::meta_config::MetaConfig, proxy_crate_gen::create_file, proxy_generator::ProxyGenerator, }; +const PROXY_COMPARE_ERR_MSG: &str = "Contract has been modified and proxies have not been updated. Regenerate proxies to avoid inconsistencies."; + impl MetaConfig { pub fn generate_proxy(&mut self) { let default_proxy = ProxyConfigSerde::new(); @@ -14,6 +19,28 @@ impl MetaConfig { write_proxy_with_explicit_path(&proxy_config, self); } } + + pub fn compare_proxy(&mut self) { + for proxy_config in self.sc_config.proxy_configs.clone() { + compare_proxy_explicit_path(&proxy_config, self); + } + } +} + +fn compare_proxy_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &MetaConfig) { + let contract_abi = extract_contract_abi(proxy_config, meta_config); + let mut temp = Vec::::new(); + let mut proxy_generator = + ProxyGenerator::new(meta_config, &mut temp, proxy_config, contract_abi); + proxy_generator.write_proxy_to_file(); + + let existent_proxy_path = format!("../{}", proxy_config.path); + let existent_proxy = fs::read_to_string(existent_proxy_path).unwrap(); + let newly_gen_proxy = String::from_utf8(temp).unwrap(); + + if existent_proxy != newly_gen_proxy { + panic!("{}", PROXY_COMPARE_ERR_MSG.to_string().red()); + } } fn write_proxy_with_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &MetaConfig) { diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs index 015d7afc90..79a25ad838 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs @@ -1,4 +1,4 @@ -use std::{fmt::Display, fs::File, io::Write}; +use std::fmt::Display; use multiversx_sc::abi::{ ContractAbi, EndpointAbi, EnumVariantDescription, InputAbi, OutputAbi, StructFieldDescription, @@ -41,7 +41,7 @@ const TYPES_FROM_FRAMEWORK: &[&str] = &[ pub struct ProxyGenerator<'a> { pub meta_config: &'a MetaConfig, - pub file: Option<&'a mut File>, + pub file: Option<&'a mut dyn std::io::Write>, pub proxy_config: &'a ProxyConfigSerde, pub contract_abi: &'a ContractAbi, } @@ -49,7 +49,7 @@ pub struct ProxyGenerator<'a> { impl<'a> ProxyGenerator<'a> { pub fn new( meta_config: &'a MetaConfig, - file: &'a mut File, + file: &'a mut dyn std::io::Write, proxy_config: &'a ProxyConfigSerde, contract_abi: &'a ContractAbi, ) -> Self { @@ -62,8 +62,8 @@ impl<'a> ProxyGenerator<'a> { } fn write(&mut self, s: impl Display) { - let file = self.file.as_mut().expect("output not configured"); - write!(*file, "{s}").unwrap(); + let file = self.file.as_mut().unwrap(); + file.write_all(s.to_string().as_bytes()).unwrap(); } fn writeln(&mut self, s: impl Display) {