From 865040c8408c4d0aa4b8103e97322688dc8bc91a Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 12 Jul 2024 03:29:42 +0200 Subject: [PATCH 01/52] impl tries --- .../adder/tests/adder_whitebox_test.rs | 46 ++++++- framework/scenario/src/facade/world_tx.rs | 2 + .../facade/world_tx/scenario_tx_whitebox.rs | 117 ++++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 9e7abe4a51..54610cbbad 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -2,11 +2,14 @@ use adder::*; use multiversx_sc_scenario::imports::*; const ADDER_PATH_EXPR: &str = "mxsc:output/adder.mxsc.json"; +const OWNER: TestAddress = TestAddress::new("owner"); +const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); +const CODE_PATH: MxscPath = MxscPath::new("mxsc:output/adder.mxsc.json"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract("mxsc:output/adder.mxsc.json", adder::ContractBuilder); + blockchain.register_contract(CODE_PATH, adder::ContractBuilder); blockchain } @@ -47,3 +50,44 @@ fn adder_whitebox() { ), ); } + +#[test] +fn adder_whitebox_unified() { + let mut world = world(); + + world.account(OWNER).nonce(1); + + let _new_address = world + .tx() + .from(OWNER) + .raw_deploy() + .code(CODE_PATH) + .new_address(ADDER_ADDRESS) + .with_result(ExpectError(0, "ok")) + .returns(ReturnsNewBech32Address) + .whitebox(adder::contract_obj::(), |sc| { + sc.init(5u32.into()); + }); + + world + .tx() + .from(OWNER) + .to(ADDER_ADDRESS) + .raw_call("") + .returns(ExpectError(0u64, "ok")) + .whitebox(adder::contract_obj::(), |sc| { + sc.add(5u32.into()); + }); + + let _raw_response = world + .query() + .to(ADDER_ADDRESS) + .raw_call("") + .returns(ReturnsRawResult) + .whitebox(adder::contract_obj::(), |sc| { + let sum = sc.sum().get(); + assert_eq!(sum, BigUint::from(10u64)); + }); + + assert_eq!(new_address, ADDER_ADDRESS); +} diff --git a/framework/scenario/src/facade/world_tx.rs b/framework/scenario/src/facade/world_tx.rs index a2d7373a42..d052614297 100644 --- a/framework/scenario/src/facade/world_tx.rs +++ b/framework/scenario/src/facade/world_tx.rs @@ -5,7 +5,9 @@ mod scenario_query_call; mod scenario_rh_impl; mod scenario_set_state; mod scenario_tx_env; +mod scenario_tx_whitebox; pub use scenario_exec_call::ScenarioEnvExec; pub use scenario_query_call::ScenarioEnvQuery; pub use scenario_tx_env::{ScenarioTxEnv, ScenarioTxEnvData, ScenarioTxRun}; +pub use scenario_tx_whitebox::ScenarioTxWhitebox; diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs new file mode 100644 index 0000000000..933af47cc5 --- /dev/null +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -0,0 +1,117 @@ +use crate::scenario::tx_to_step::TxToQueryStep; +use crate::ScenarioEnvQuery; +use crate::{ + imports::StaticApi, + scenario::{run_vm::ScenarioVMRunner, tx_to_step::TxToStep}, + scenario_model::TxResponse, + ScenarioEnvExec, +}; +use multiversx_sc::{ + tuple_util::NestedTupleFlatten, + types::{ + Code, DeployCall, FunctionCall, RHListExec, Tx, TxCodeValue, TxFromSpecified, TxNoPayment, + TxPayment, TxToSpecified, + }, +}; + +pub trait ScenarioTxWhitebox { + type Returns; + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns; +} + +pub struct ContractObj +where + A: multiversx_sc::api::VMApi, +{ + _phantom: core::marker::PhantomData, +} + +impl<'w, From, Payment, CodeValue, RH> ScenarioTxWhitebox + for Tx< + ScenarioEnvExec<'w>, + From, + (), + Payment, + (), + DeployCall, Code>, + RH, + > +where + From: TxFromSpecified>, + Payment: TxNoPayment>, + CodeValue: TxCodeValue>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns { + let step_wrapper = self.tx_to_step(); + + let mut scenario_vm_runner = ScenarioVMRunner::new(); + let (_new_addr, _tx_result) = + scenario_vm_runner.perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); + + step_wrapper.process_result() + } +} + +impl<'w, From, To, Payment, RH> ScenarioTxWhitebox + for Tx, From, To, Payment, (), FunctionCall, RH> +where + From: TxFromSpecified>, + To: TxToSpecified>, + Payment: TxPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns { + let step_wrapper = self.tx_to_step(); + let _tx_result = self + .env + .world + .get_mut_debugger_backend() + .vm_runner + .perform_sc_call_lambda(&step_wrapper.step, || f(contract_obj)); + + step_wrapper.process_result() + } +} + +impl<'w, To, Payment, RH> ScenarioTxWhitebox + for Tx, (), To, Payment, (), FunctionCall, RH> +where + To: TxToSpecified>, + Payment: TxNoPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj: ContractObj, + f: F, + ) -> Self::Returns { + let step_wrapper = self.tx_to_query_step(); + + let mut scenario_vm_runner = ScenarioVMRunner::new(); + let _tx_result = + scenario_vm_runner.perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + step_wrapper.process_result() + } +} From dbdb627f41e35c2c4ae18f9d552060c8d748c2e7 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 12 Jul 2024 17:53:41 +0200 Subject: [PATCH 02/52] fix debugger backend issue --- .../adder/tests/adder_whitebox_test.rs | 4 +-- .../facade/world_tx/scenario_tx_whitebox.rs | 34 ++++++++----------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 54610cbbad..92f13a2bb3 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -69,6 +69,8 @@ fn adder_whitebox_unified() { sc.init(5u32.into()); }); + assert_eq!(_new_address, ADDER_ADDRESS.to_address().into()); + world .tx() .from(OWNER) @@ -88,6 +90,4 @@ fn adder_whitebox_unified() { let sum = sc.sum().get(); assert_eq!(sum, BigUint::from(10u64)); }); - - assert_eq!(new_address, ADDER_ADDRESS); } diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 933af47cc5..0d9040a2ee 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -1,10 +1,7 @@ use crate::scenario::tx_to_step::TxToQueryStep; use crate::ScenarioEnvQuery; use crate::{ - imports::StaticApi, - scenario::{run_vm::ScenarioVMRunner, tx_to_step::TxToStep}, - scenario_model::TxResponse, - ScenarioEnvExec, + imports::StaticApi, scenario::tx_to_step::TxToStep, scenario_model::TxResponse, ScenarioEnvExec, }; use multiversx_sc::{ tuple_util::NestedTupleFlatten, @@ -23,13 +20,6 @@ pub trait ScenarioTxWhitebox { ) -> Self::Returns; } -pub struct ContractObj -where - A: multiversx_sc::api::VMApi, -{ - _phantom: core::marker::PhantomData, -} - impl<'w, From, Payment, CodeValue, RH> ScenarioTxWhitebox for Tx< ScenarioEnvExec<'w>, @@ -55,10 +45,12 @@ where f: F, ) -> Self::Returns { let step_wrapper = self.tx_to_step(); - - let mut scenario_vm_runner = ScenarioVMRunner::new(); - let (_new_addr, _tx_result) = - scenario_vm_runner.perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); + let (_new_addr, _tx_result) = step_wrapper + .env + .world + .get_mut_debugger_backend() + .vm_runner + .perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); step_wrapper.process_result() } @@ -81,7 +73,7 @@ where f: F, ) -> Self::Returns { let step_wrapper = self.tx_to_step(); - let _tx_result = self + let _tx_result = step_wrapper .env .world .get_mut_debugger_backend() @@ -109,9 +101,13 @@ where ) -> Self::Returns { let step_wrapper = self.tx_to_query_step(); - let mut scenario_vm_runner = ScenarioVMRunner::new(); - let _tx_result = - scenario_vm_runner.perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + let _tx_result = step_wrapper + .env + .world + .get_mut_debugger_backend() + .vm_runner + .perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + step_wrapper.process_result() } } From dfb43b9c4a222ebae7977de7ef21de3a6d03e31c Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 12 Jul 2024 20:24:20 +0200 Subject: [PATCH 03/52] changed contract obj api --- contracts/examples/adder/tests/adder_whitebox_test.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 92f13a2bb3..726e1ab18a 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -65,8 +65,8 @@ fn adder_whitebox_unified() { .new_address(ADDER_ADDRESS) .with_result(ExpectError(0, "ok")) .returns(ReturnsNewBech32Address) - .whitebox(adder::contract_obj::(), |sc| { - sc.init(5u32.into()); + .whitebox(adder::contract_obj::(), |sc| { + sc.init(BigUint::from(5u64)); }); assert_eq!(_new_address, ADDER_ADDRESS.to_address().into()); @@ -77,8 +77,8 @@ fn adder_whitebox_unified() { .to(ADDER_ADDRESS) .raw_call("") .returns(ExpectError(0u64, "ok")) - .whitebox(adder::contract_obj::(), |sc| { - sc.add(5u32.into()); + .whitebox(adder::contract_obj::(), |sc| { + sc.add(BigUint::from(5u64)); }); let _raw_response = world @@ -86,7 +86,7 @@ fn adder_whitebox_unified() { .to(ADDER_ADDRESS) .raw_call("") .returns(ReturnsRawResult) - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj::(), |sc| { let sum = sc.sum().get(); assert_eq!(sum, BigUint::from(10u64)); }); From 3fc34101fb85f911cde6825815431145af2a8d9e Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Wed, 31 Jul 2024 16:46:13 +0300 Subject: [PATCH 04/52] return new node id on insert element --- .../src/storage/mappers/ordered_binary_tree_mapper.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs b/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs index 064e90551c..2425c59049 100644 --- a/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs +++ b/framework/base/src/storage/mappers/ordered_binary_tree_mapper.rs @@ -232,7 +232,7 @@ where opt_predecessor } - pub fn insert_element(&mut self, new_data: T) { + pub fn insert_element(&mut self, new_data: T) -> u64 { let new_node_id = self.get_and_increment_last_id(); let mut new_node = OrderedBinaryTreeNode::new(new_node_id, new_data); @@ -243,7 +243,7 @@ where let current_node = unsafe { opt_current_node.unwrap_unchecked() }; if new_node.data == current_node.data { - return; + return 0u64; } if new_node.data < current_node.data { @@ -266,7 +266,7 @@ where let root_key = self.build_root_key(); storage_set(root_key.as_ref(), &new_node); - return; + return 0u64; } let mut new_node_parent = unsafe { opt_new_node_parent.unwrap_unchecked() }; @@ -278,6 +278,8 @@ where self.set_item(new_node_id, &new_node); self.set_item(new_node_parent.current_node_id, &new_node_parent); + + new_node_id } pub fn delete_node(&mut self, data: T) { From b98c1f712b13678d69e9804ad4a4817b53356375 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 12 Aug 2024 15:50:43 +0300 Subject: [PATCH 05/52] pem wallet generation --- Cargo.lock | 1 + framework/meta/Cargo.toml | 4 ++ framework/meta/src/cli/cli_args_standalone.rs | 58 +++++++++++++++++++ framework/meta/src/cli/cli_standalone_main.rs | 4 ++ framework/meta/src/cmd.rs | 1 + framework/meta/src/cmd/wallet.rs | 53 +++++++++++++++++ 6 files changed, 121 insertions(+) create mode 100644 framework/meta/src/cmd/wallet.rs diff --git a/Cargo.lock b/Cargo.lock index abeb3c37e1..4ae509e714 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,6 +1996,7 @@ dependencies = [ "multiversx-sc", "multiversx-sc-meta-lib", "multiversx-sc-snippets", + "multiversx-sdk", "pathdiff", "reqwest", "ruplacer", diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index bd6775ed1a..0aebe72194 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -52,3 +52,7 @@ features = ["alloc", "num-bigint"] [dependencies.multiversx-sc-snippets] version = "=0.52.3" path = "../snippets" + +[dependencies.multiversx-sdk] +version = "=0.5.0" +path = "../../sdk/core" diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index 335afe41ea..38857c6f9e 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -75,6 +75,12 @@ pub enum StandaloneCliAction { about = "Generates a report on the local depedencies of contract crates. Will explore indirect depdencies too." )] LocalDeps(LocalDepsArgs), + + #[command( + name = "wallet", + about = "Generates a new wallet or performs actions on an existing wallet." + )] + Wallet(WalletArgs), } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] @@ -348,3 +354,55 @@ pub struct AccountArgs { #[arg(long = "address", verbatim_doc_comment)] pub address: String, } + +#[derive(Clone, PartialEq, Eq, Debug, Subcommand)] +pub enum WalletAction { + #[command(name = "new", about = "Creates a new wallet")] + New(WalletNewArgs), + + #[command(name = "convert", about = "Converts a wallet")] + Convert(WalletConvertArgs), +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] +pub enum WalletFormat { + #[default] + Pem, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] +pub enum WalletConvertFormat { + #[default] + Bech32, + + Hex, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Parser)] +#[command(propagate_version = true)] +pub struct WalletArgs { + #[command(subcommand)] + pub command: Option, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct WalletNewArgs { + /// The type of wallet to create. + #[arg(long = "format", verbatim_doc_comment)] + pub wallet_format: Option, + + /// The name of the wallet to create. + #[arg(long = "outfile", verbatim_doc_comment)] + pub outfile: Option, + // #[arg(long = "address-hrp")] + // pub address_hrp: Option, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct WalletConvertArgs { + #[arg(long = "from", verbatim_doc_comment)] + pub from: Option, + + #[arg(long = "to", verbatim_doc_comment)] + pub to: Option, +} diff --git a/framework/meta/src/cli/cli_standalone_main.rs b/framework/meta/src/cli/cli_standalone_main.rs index 6c8c6a67b0..5100750abc 100644 --- a/framework/meta/src/cli/cli_standalone_main.rs +++ b/framework/meta/src/cli/cli_standalone_main.rs @@ -1,5 +1,6 @@ use crate::cli::{StandaloneCliAction, StandaloneCliArgs}; use crate::cmd::retrieve_address::retrieve_address; +use crate::cmd::wallet::wallet; use clap::Parser; use crate::cmd::all::call_all_meta; @@ -41,6 +42,9 @@ pub async fn cli_main_standalone() { Some(StandaloneCliAction::LocalDeps(args)) => { local_deps(args); }, + Some(StandaloneCliAction::Wallet(args)) => { + wallet(args); + }, None => {}, } } diff --git a/framework/meta/src/cmd.rs b/framework/meta/src/cmd.rs index a588f90162..8053a2113e 100644 --- a/framework/meta/src/cmd.rs +++ b/framework/meta/src/cmd.rs @@ -9,3 +9,4 @@ pub mod template; pub mod test; pub mod test_coverage; pub mod upgrade; +pub mod wallet; diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs new file mode 100644 index 0000000000..4ad0a3f7d9 --- /dev/null +++ b/framework/meta/src/cmd/wallet.rs @@ -0,0 +1,53 @@ +use std::{fs::File, io::Write}; + +use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletFormat, WalletNewArgs}; +use multiversx_sdk::{data::address::Address, wallet::Wallet}; + +pub fn wallet(args: &WalletArgs) { + let command = args + .command + .as_ref() + .expect("command expected after `wallet`"); + match command { + WalletAction::New(new_args) => new(new_args), + WalletAction::Convert(convert_args) => convert(convert_args), + } +} + +fn convert(convert_args: &WalletConvertArgs) { + todo!() +} + +fn new(new_args: &WalletNewArgs) { + let format = new_args + .wallet_format + .as_ref() + .expect("wallet format is required"); + let outfile = new_args.outfile.as_ref().expect("output file is required"); + + match format { + WalletFormat::Pem => { + let mnemonic = Wallet::generate_mnemonic(); + let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); + let pk_str: &str = &private_key.to_string(); + let wallet = Wallet::from_private_key(pk_str).unwrap(); + let address = wallet.address(); + + println!("Wallet address: {}", address); + + generate_pem(&address, pk_str, outfile); + }, + } +} + +fn generate_pem(address: &Address, private_key: &str, outfile: &String) { + let pem_content = format!( + "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----", + address.to_bech32_string().unwrap(), + private_key, + address.to_bech32_string().unwrap() + ); + + let mut file = File::create(outfile).unwrap(); + file.write_all(pem_content.as_bytes()).unwrap() +} From b530c1f6a712538be16e01c47a541e1c6cafd74d Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 12 Aug 2024 18:52:33 +0300 Subject: [PATCH 06/52] [WIP] generated pem file --- Cargo.lock | 19 +++-- framework/meta/Cargo.toml | 1 + framework/meta/src/cli/cli_args_standalone.rs | 32 +++----- framework/meta/src/cmd/wallet.rs | 77 +++++++++++++++++-- 4 files changed, 95 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ae509e714..08f2acc6ae 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,6 +195,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.22.1" @@ -1988,6 +1994,7 @@ dependencies = [ name = "multiversx-sc-meta" version = "0.52.3" dependencies = [ + "base64 0.13.1", "clap", "colored", "common-path", @@ -2038,7 +2045,7 @@ dependencies = [ name = "multiversx-sc-scenario" version = "0.52.3" dependencies = [ - "base64", + "base64 0.22.1", "bech32", "colored", "hex", @@ -2062,7 +2069,7 @@ dependencies = [ name = "multiversx-sc-snippets" version = "0.52.3" dependencies = [ - "base64", + "base64 0.22.1", "env_logger", "futures", "hex", @@ -2086,7 +2093,7 @@ name = "multiversx-sdk" version = "0.5.0" dependencies = [ "anyhow", - "base64", + "base64 0.22.1", "bech32", "bip39", "hex", @@ -2424,7 +2431,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64", + "base64 0.22.1", "serde", ] @@ -2756,7 +2763,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-channel", @@ -2926,7 +2933,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index 0aebe72194..c59184d411 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -39,6 +39,7 @@ zip = { version = "2.1", features = ["deflate"], default-features = false } copy_dir = "0.1.2" pathdiff = "0.2.1" common-path = "1.0.0" +base64 = "0.13" [dependencies.multiversx-sc-meta-lib] version = "=0.52.3" diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index 38857c6f9e..d670987338 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -364,20 +364,6 @@ pub enum WalletAction { Convert(WalletConvertArgs), } -#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] -pub enum WalletFormat { - #[default] - Pem, -} - -#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)] -pub enum WalletConvertFormat { - #[default] - Bech32, - - Hex, -} - #[derive(Default, Clone, PartialEq, Eq, Debug, Parser)] #[command(propagate_version = true)] pub struct WalletArgs { @@ -389,20 +375,24 @@ pub struct WalletArgs { pub struct WalletNewArgs { /// The type of wallet to create. #[arg(long = "format", verbatim_doc_comment)] - pub wallet_format: Option, + pub wallet_format: Option, /// The name of the wallet to create. #[arg(long = "outfile", verbatim_doc_comment)] pub outfile: Option, - // #[arg(long = "address-hrp")] - // pub address_hrp: Option, } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct WalletConvertArgs { - #[arg(long = "from", verbatim_doc_comment)] - pub from: Option, + #[arg(long = "in-format", verbatim_doc_comment)] + pub from: Option, - #[arg(long = "to", verbatim_doc_comment)] - pub to: Option, + #[arg(long = "out-format", verbatim_doc_comment)] + pub to: Option, + + #[arg(long = "infile", verbatim_doc_comment)] + pub infile: Option, + + #[arg(long = "outfile", verbatim_doc_comment)] + pub outfile: Option, } diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index 4ad0a3f7d9..b1fdddee9c 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,6 +1,12 @@ -use std::{fs::File, io::Write}; +use base64; +use core::str; +use std::{ + fs::{self, File}, + io::Write, +}; -use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletFormat, WalletNewArgs}; +use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletNewArgs}; +use multiversx_sc_snippets::{hex, imports::Bech32Address}; use multiversx_sdk::{data::address::Address, wallet::Wallet}; pub fn wallet(args: &WalletArgs) { @@ -15,7 +21,46 @@ pub fn wallet(args: &WalletArgs) { } fn convert(convert_args: &WalletConvertArgs) { - todo!() + let infile = convert_args + .infile + .as_ref() + .expect("input file is required"); + let outfile = convert_args.outfile.as_ref(); + let in_format = convert_args + .from + .as_ref() + .expect("input format is required"); + let out_format = convert_args.to.as_ref().expect("output format is required"); + + let in_address = fs::read_to_string(infile).unwrap(); + let mut out_addr: String = String::from(""); + + match (in_format.as_str(), out_format.as_str()) { + ("address-bech32", "address-hex") => { + out_addr = Bech32Address::from_bech32_string(in_address).to_hex(); + }, + ("address-hex", "address-bech32") => { + // out_addr = Bech32Address::from(in_address).to_bech32_string(); + let bytes_from_hex: [u8; 64] = hex::decode(in_address).unwrap().try_into().unwrap(); + out_addr = Bech32Address::from_bech32_string( + str::from_utf8(&bytes_from_hex).unwrap().to_string(), + ) + .to_bech32_string(); + }, + _ => { + println!("Unsupported conversion"); + }, + } + + match outfile { + Some(outfile) => { + let mut file = File::create(outfile).unwrap(); + file.write_all(out_addr.as_bytes()).unwrap(); + }, + None => { + println!("{}", out_addr); + }, + } } fn new(new_args: &WalletNewArgs) { @@ -25,8 +70,8 @@ fn new(new_args: &WalletNewArgs) { .expect("wallet format is required"); let outfile = new_args.outfile.as_ref().expect("output file is required"); - match format { - WalletFormat::Pem => { + match format.as_str() { + "pem" => { let mnemonic = Wallet::generate_mnemonic(); let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); let pk_str: &str = &private_key.to_string(); @@ -37,14 +82,32 @@ fn new(new_args: &WalletNewArgs) { generate_pem(&address, pk_str, outfile); }, + _ => { + println!("Unsupported wallet format"); + }, } } fn generate_pem(address: &Address, private_key: &str, outfile: &String) { + println!("{private_key}"); + let private_key_hex_encoded = hex::encode(private_key.as_bytes()); + println!("HEX {private_key_hex_encoded}"); + // let priv_key_bytes = private_key_hex_encoded.as_bytes(); + let private_key_base64 = base64::encode(&private_key_hex_encoded.as_bytes()); + println!("B64 {private_key_base64}"); + + // Split the base64 string into 64-character lines + let formatted_key = private_key_base64 + .as_bytes() + .chunks(64) + .map(|chunk| std::str::from_utf8(chunk).unwrap()) + .collect::>() + .join("\n"); + let pem_content = format!( - "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----", + "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----\n", address.to_bech32_string().unwrap(), - private_key, + formatted_key, address.to_bech32_string().unwrap() ); From d5be23d47cd28e9aae627899dc80d85302d2e5c6 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 13 Aug 2024 13:09:31 +0300 Subject: [PATCH 07/52] demo wallet creation & conversion --- framework/meta/src/cli/cli_args_standalone.rs | 4 +- framework/meta/src/cmd/wallet.rs | 105 ++++++++++-------- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index d670987338..59cb0a4d86 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -385,10 +385,10 @@ pub struct WalletNewArgs { #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct WalletConvertArgs { #[arg(long = "in-format", verbatim_doc_comment)] - pub from: Option, + pub from: String, #[arg(long = "out-format", verbatim_doc_comment)] - pub to: Option, + pub to: String, #[arg(long = "infile", verbatim_doc_comment)] pub infile: Option, diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index b1fdddee9c..bdddf81b60 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,13 +1,14 @@ use base64; use core::str; +use multiversx_sc::types; use std::{ fs::{self, File}, - io::Write, + io::{self, Read, Write}, }; use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletNewArgs}; use multiversx_sc_snippets::{hex, imports::Bech32Address}; -use multiversx_sdk::{data::address::Address, wallet::Wallet}; +use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wallet::Wallet}; pub fn wallet(args: &WalletArgs) { let command = args @@ -21,31 +22,37 @@ pub fn wallet(args: &WalletArgs) { } fn convert(convert_args: &WalletConvertArgs) { - let infile = convert_args - .infile - .as_ref() - .expect("input file is required"); + let infile = convert_args.infile.as_ref(); let outfile = convert_args.outfile.as_ref(); - let in_format = convert_args - .from - .as_ref() - .expect("input format is required"); - let out_format = convert_args.to.as_ref().expect("output format is required"); + let in_format = &convert_args.from; + let out_format = &convert_args.to; + + let mut in_address = String::new(); + let mut out_address: String = String::new(); + + match infile { + Some(file) => in_address = fs::read_to_string(file).unwrap(), + None => { + println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); + _ = io::stdin().read_to_string(&mut in_address).unwrap() + }, + } - let in_address = fs::read_to_string(infile).unwrap(); - let mut out_addr: String = String::from(""); + in_address = in_address.replace('\n', ""); match (in_format.as_str(), out_format.as_str()) { ("address-bech32", "address-hex") => { - out_addr = Bech32Address::from_bech32_string(in_address).to_hex(); + out_address = Bech32Address::from_bech32_string(in_address).to_hex(); }, ("address-hex", "address-bech32") => { - // out_addr = Bech32Address::from(in_address).to_bech32_string(); - let bytes_from_hex: [u8; 64] = hex::decode(in_address).unwrap().try_into().unwrap(); - out_addr = Bech32Address::from_bech32_string( - str::from_utf8(&bytes_from_hex).unwrap().to_string(), - ) - .to_bech32_string(); + let bytes_from_hex = hex::decode(in_address).unwrap(); + let bytes_arr: [u8; 32] = bytes_from_hex.try_into().unwrap(); + + let addr = types::Address::from(&bytes_arr); + out_address = Bech32Address::from(addr).to_bech32_str().to_string(); + }, + ("", _) | (_, "") => { + println!("error: the following arguments are required: --in-format, --out-format"); }, _ => { println!("Unsupported conversion"); @@ -55,49 +62,51 @@ fn convert(convert_args: &WalletConvertArgs) { match outfile { Some(outfile) => { let mut file = File::create(outfile).unwrap(); - file.write_all(out_addr.as_bytes()).unwrap(); + out_address.push('\n'); + file.write_all(out_address.as_bytes()).unwrap(); }, None => { - println!("{}", out_addr); + println!("{}", out_address); }, } } fn new(new_args: &WalletNewArgs) { - let format = new_args - .wallet_format - .as_ref() - .expect("wallet format is required"); - let outfile = new_args.outfile.as_ref().expect("output file is required"); + let format = new_args.wallet_format.as_ref(); + let outfile = new_args.outfile.as_ref(); + let mnemonic = Wallet::generate_mnemonic(); + println!("Mnemonic: {}", mnemonic); - match format.as_str() { - "pem" => { - let mnemonic = Wallet::generate_mnemonic(); - let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); - let pk_str: &str = &private_key.to_string(); - let wallet = Wallet::from_private_key(pk_str).unwrap(); - let address = wallet.address(); + let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); + let public_key = PublicKey::from(&private_key); - println!("Wallet address: {}", address); + let public_key_str: &str = &public_key.to_string(); + let private_key_str: &str = &private_key.to_string(); - generate_pem(&address, pk_str, outfile); - }, - _ => { - println!("Unsupported wallet format"); - }, + let wallet = Wallet::from_private_key(private_key_str).unwrap(); + let address = wallet.address(); + + println!("Wallet address: {}", address); + + if let Some(f) = format { + match (f.as_str(), outfile) { + ("pem", Some(file)) => { + generate_pem(&address, private_key_str, public_key_str, file); + }, + ("pem", None) => { + println!("Output file is required for PEM format"); + }, + _ => {}, + } } } -fn generate_pem(address: &Address, private_key: &str, outfile: &String) { - println!("{private_key}"); - let private_key_hex_encoded = hex::encode(private_key.as_bytes()); - println!("HEX {private_key_hex_encoded}"); - // let priv_key_bytes = private_key_hex_encoded.as_bytes(); - let private_key_base64 = base64::encode(&private_key_hex_encoded.as_bytes()); - println!("B64 {private_key_base64}"); +fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: &String) { + let concat_keys = format!("{}{}", private_key, public_key); + let concat_keys_b64 = base64::encode(concat_keys); // Split the base64 string into 64-character lines - let formatted_key = private_key_base64 + let formatted_key = concat_keys_b64 .as_bytes() .chunks(64) .map(|chunk| std::str::from_utf8(chunk).unwrap()) From 47ef8de7f75ed1c031b448d00579debefa2e0941 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 13 Aug 2024 17:03:47 +0300 Subject: [PATCH 08/52] added bech32 command and updated conversion --- framework/meta/Cargo.toml | 2 +- framework/meta/src/cli/cli_args_standalone.rs | 17 ++- framework/meta/src/cmd/wallet.rs | 132 +++++++++++------- 3 files changed, 101 insertions(+), 50 deletions(-) diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index c59184d411..63625c1746 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -39,7 +39,7 @@ zip = { version = "2.1", features = ["deflate"], default-features = false } copy_dir = "0.1.2" pathdiff = "0.2.1" common-path = "1.0.0" -base64 = "0.13" +bip39 = "2.0.0" [dependencies.multiversx-sc-meta-lib] version = "=0.52.3" diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index 59cb0a4d86..104feac18d 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -360,15 +360,20 @@ pub enum WalletAction { #[command(name = "new", about = "Creates a new wallet")] New(WalletNewArgs), + #[command( + name = "bech32", + about = "Encodes/decodes a bech32 address to/from hex" + )] + Bech32(WalletBech32Args), #[command(name = "convert", about = "Converts a wallet")] Convert(WalletConvertArgs), } -#[derive(Default, Clone, PartialEq, Eq, Debug, Parser)] +#[derive(Clone, PartialEq, Eq, Debug, Parser)] #[command(propagate_version = true)] pub struct WalletArgs { #[command(subcommand)] - pub command: Option, + pub command: WalletAction, } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] @@ -396,3 +401,11 @@ pub struct WalletConvertArgs { #[arg(long = "outfile", verbatim_doc_comment)] pub outfile: Option, } + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct WalletBech32Args { + #[arg(long = "encode", verbatim_doc_comment)] + pub hex_address: Option, + #[arg(long = "decode", verbatim_doc_comment)] + pub bech32_address: Option, +} diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index bdddf81b60..7ed5ea58bb 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,4 +1,3 @@ -use base64; use core::str; use multiversx_sc::types; use std::{ @@ -6,17 +5,17 @@ use std::{ io::{self, Read, Write}, }; -use crate::cli::{WalletAction, WalletArgs, WalletConvertArgs, WalletNewArgs}; +use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; +use bip39::Mnemonic; use multiversx_sc_snippets::{hex, imports::Bech32Address}; -use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wallet::Wallet}; - +use multiversx_sdk::{ + crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, +}; pub fn wallet(args: &WalletArgs) { - let command = args - .command - .as_ref() - .expect("command expected after `wallet`"); + let command = &args.command; match command { WalletAction::New(new_args) => new(new_args), + WalletAction::Bech32(bech32_args) => bech32_conversion(bech32_args), WalletAction::Convert(convert_args) => convert(convert_args), } } @@ -27,71 +26,105 @@ fn convert(convert_args: &WalletConvertArgs) { let in_format = &convert_args.from; let out_format = &convert_args.to; - let mut in_address = String::new(); - let mut out_address: String = String::new(); - - match infile { - Some(file) => in_address = fs::read_to_string(file).unwrap(), - None => { - println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); - _ = io::stdin().read_to_string(&mut in_address).unwrap() - }, - } - - in_address = in_address.replace('\n', ""); + let mut mnemonic_str = String::new(); match (in_format.as_str(), out_format.as_str()) { - ("address-bech32", "address-hex") => { - out_address = Bech32Address::from_bech32_string(in_address).to_hex(); - }, - ("address-hex", "address-bech32") => { - let bytes_from_hex = hex::decode(in_address).unwrap(); - let bytes_arr: [u8; 32] = bytes_from_hex.try_into().unwrap(); - - let addr = types::Address::from(&bytes_arr); - out_address = Bech32Address::from(addr).to_bech32_str().to_string(); - }, - ("", _) | (_, "") => { - println!("error: the following arguments are required: --in-format, --out-format"); + ("mnemonic", "pem") => match infile { + Some(file) => { + mnemonic_str = fs::read_to_string(file).unwrap(); + mnemonic_str = mnemonic_str.replace('\n', ""); + }, + None => { + println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); + _ = io::stdin().read_to_string(&mut mnemonic_str).unwrap() + }, }, _ => { println!("Unsupported conversion"); }, } + let mnemonic = Mnemonic::parse(mnemonic_str).unwrap(); + + let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); + let address = get_wallet_address(private_key_str.as_str()); + match outfile { Some(outfile) => { - let mut file = File::create(outfile).unwrap(); - out_address.push('\n'); - file.write_all(out_address.as_bytes()).unwrap(); + generate_pem( + &address, + private_key_str.as_str(), + public_key_str.as_str(), + outfile, + ); }, None => { - println!("{}", out_address); + let pem_content = + generate_pem_content(&address, private_key_str.as_str(), public_key_str.as_str()); + print!("{}", pem_content); }, } } -fn new(new_args: &WalletNewArgs) { - let format = new_args.wallet_format.as_ref(); - let outfile = new_args.outfile.as_ref(); - let mnemonic = Wallet::generate_mnemonic(); - println!("Mnemonic: {}", mnemonic); +fn bech32_conversion(bech32_args: &WalletBech32Args) { + let encode_address = bech32_args.hex_address.as_ref(); + let decode_address = bech32_args.bech32_address.as_ref(); + + match (encode_address, decode_address) { + (Some(hex), None) => { + let bytes_from_hex = hex::decode(hex).unwrap(); + let bytes_arr: [u8; 32] = bytes_from_hex.try_into().unwrap(); + let addr = types::Address::from(&bytes_arr); + let bech32_addr = Bech32Address::from(addr).to_bech32_str().to_string(); + println!("{}", bech32_addr); + }, + (None, Some(bech32)) => { + let hex_addr = Bech32Address::from_bech32_string(bech32.to_string()).to_hex(); + println!("{}", hex_addr); + }, + (Some(_), Some(_)) => { + println!("error: only one of --encode or --decode can be used in the same command"); + }, + _ => {}, + } +} + +fn get_wallet_keys(mnemonic: Mnemonic) -> (String, String) { let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); let public_key = PublicKey::from(&private_key); let public_key_str: &str = &public_key.to_string(); let private_key_str: &str = &private_key.to_string(); - let wallet = Wallet::from_private_key(private_key_str).unwrap(); - let address = wallet.address(); + (private_key_str.to_string(), public_key_str.to_string()) +} + +fn get_wallet_address(private_key: &str) -> Address { + let wallet = Wallet::from_private_key(private_key).unwrap(); + wallet.address() +} + +fn new(new_args: &WalletNewArgs) { + let format = new_args.wallet_format.as_ref(); + let outfile = new_args.outfile.as_ref(); + let mnemonic = Wallet::generate_mnemonic(); + println!("Mnemonic: {}", mnemonic); + + let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); + let address = get_wallet_address(private_key_str.as_str()); println!("Wallet address: {}", address); if let Some(f) = format { match (f.as_str(), outfile) { ("pem", Some(file)) => { - generate_pem(&address, private_key_str, public_key_str, file); + generate_pem( + &address, + private_key_str.as_str(), + public_key_str.as_str(), + file, + ); }, ("pem", None) => { println!("Output file is required for PEM format"); @@ -102,8 +135,14 @@ fn new(new_args: &WalletNewArgs) { } fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: &String) { + let pem_content = generate_pem_content(address, private_key, public_key); + let mut file = File::create(outfile).unwrap(); + file.write_all(pem_content.as_bytes()).unwrap() +} + +fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { let concat_keys = format!("{}{}", private_key, public_key); - let concat_keys_b64 = base64::encode(concat_keys); + let concat_keys_b64 = base64_encode(concat_keys); // Split the base64 string into 64-character lines let formatted_key = concat_keys_b64 @@ -120,6 +159,5 @@ fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: address.to_bech32_string().unwrap() ); - let mut file = File::create(outfile).unwrap(); - file.write_all(pem_content.as_bytes()).unwrap() + pem_content } From eba0141dee9f708136bf2560255decb736be56b4 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 13 Aug 2024 17:50:45 +0300 Subject: [PATCH 09/52] deleted unnecessary dependency --- framework/meta/Cargo.toml | 4 ---- framework/meta/src/cmd/wallet.rs | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index 63625c1746..fba796a3d0 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -53,7 +53,3 @@ features = ["alloc", "num-bigint"] [dependencies.multiversx-sc-snippets] version = "=0.52.3" path = "../snippets" - -[dependencies.multiversx-sdk] -version = "=0.5.0" -path = "../../sdk/core" diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index 7ed5ea58bb..7fcf28899a 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -7,10 +7,10 @@ use std::{ use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; use bip39::Mnemonic; -use multiversx_sc_snippets::{hex, imports::Bech32Address}; -use multiversx_sdk::{ +use multiversx_sc_snippets::sdk::{ crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, }; +use multiversx_sc_snippets::{hex, imports::Bech32Address}; pub fn wallet(args: &WalletArgs) { let command = &args.command; match command { From a483001be5dc472771410353520663b01d2acc67 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 13 Aug 2024 18:46:24 +0300 Subject: [PATCH 10/52] unified syntax - whitebox fix --- .../adder/tests/adder_whitebox_test.rs | 10 ++-- .../facade/world_tx/scenario_tx_whitebox.rs | 53 +++++++++++++++---- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 726e1ab18a..407f19440f 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -57,26 +57,24 @@ fn adder_whitebox_unified() { world.account(OWNER).nonce(1); - let _new_address = world + let new_address = world .tx() .from(OWNER) .raw_deploy() .code(CODE_PATH) .new_address(ADDER_ADDRESS) - .with_result(ExpectError(0, "ok")) .returns(ReturnsNewBech32Address) .whitebox(adder::contract_obj::(), |sc| { - sc.init(BigUint::from(5u64)); + sc.init(BigUint::from(3u64)); }); - assert_eq!(_new_address, ADDER_ADDRESS.to_address().into()); + assert_eq!(new_address, ADDER_ADDRESS.to_address().into()); world .tx() .from(OWNER) .to(ADDER_ADDRESS) .raw_call("") - .returns(ExpectError(0u64, "ok")) .whitebox(adder::contract_obj::(), |sc| { sc.add(BigUint::from(5u64)); }); @@ -88,6 +86,6 @@ fn adder_whitebox_unified() { .returns(ReturnsRawResult) .whitebox(adder::contract_obj::(), |sc| { let sum = sc.sum().get(); - assert_eq!(sum, BigUint::from(10u64)); + assert_eq!(sum, BigUint::from(8u64)); }); } diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 0d9040a2ee..406e109266 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -1,8 +1,10 @@ +use crate::debug_executor::contract_instance_wrapped_execution; use crate::scenario::tx_to_step::TxToQueryStep; use crate::ScenarioEnvQuery; use crate::{ imports::StaticApi, scenario::tx_to_step::TxToStep, scenario_model::TxResponse, ScenarioEnvExec, }; +use multiversx_chain_vm::tx_mock::TxFunctionName; use multiversx_sc::{ tuple_util::NestedTupleFlatten, types::{ @@ -44,14 +46,22 @@ where contract_obj: ContractObj, f: F, ) -> Self::Returns { - let step_wrapper = self.tx_to_step(); - let (_new_addr, _tx_result) = step_wrapper + let mut step_wrapper = self.tx_to_step(); + let (new_address, tx_result) = step_wrapper .env .world .get_mut_debugger_backend() .vm_runner - .perform_sc_deploy_lambda(&step_wrapper.step, || f(contract_obj)); + .perform_sc_deploy_lambda(&step_wrapper.step, || { + contract_instance_wrapped_execution(true, || { + f(contract_obj); + Ok(()) + }); + }); + let mut response = TxResponse::from_tx_result(tx_result); + response.new_deployed_address = Some(new_address); + step_wrapper.step.save_response(response); step_wrapper.process_result() } } @@ -72,14 +82,27 @@ where contract_obj: ContractObj, f: F, ) -> Self::Returns { - let step_wrapper = self.tx_to_step(); - let _tx_result = step_wrapper + let mut step_wrapper = self.tx_to_step(); + + // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value + if step_wrapper.step.tx.function.is_empty() { + step_wrapper.step.tx.function = TxFunctionName::WHITEBOX_CALL.to_string(); + } + + let tx_result = step_wrapper .env .world .get_mut_debugger_backend() .vm_runner - .perform_sc_call_lambda(&step_wrapper.step, || f(contract_obj)); + .perform_sc_call_lambda(&step_wrapper.step, || { + contract_instance_wrapped_execution(true, || { + f(contract_obj); + Ok(()) + }); + }); + let response = TxResponse::from_tx_result(tx_result); + step_wrapper.step.save_response(response); step_wrapper.process_result() } } @@ -99,15 +122,27 @@ where contract_obj: ContractObj, f: F, ) -> Self::Returns { - let step_wrapper = self.tx_to_query_step(); + let mut step_wrapper = self.tx_to_query_step(); + + // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value + if step_wrapper.step.tx.function.is_empty() { + step_wrapper.step.tx.function = TxFunctionName::WHITEBOX_CALL.to_string(); + } - let _tx_result = step_wrapper + let tx_result = step_wrapper .env .world .get_mut_debugger_backend() .vm_runner - .perform_sc_query_lambda(&step_wrapper.step, || f(contract_obj)); + .perform_sc_query_lambda(&step_wrapper.step, || { + contract_instance_wrapped_execution(true, || { + f(contract_obj); + Ok(()) + }); + }); + let response = TxResponse::from_tx_result(tx_result); + step_wrapper.step.save_response(response); step_wrapper.process_result() } } From 9f922b899f5c8221517b57e0e656c9e74295f5c9 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 13 Aug 2024 19:59:54 +0300 Subject: [PATCH 11/52] unified syntax - whitebox contract_obj cleanup --- .../adder/tests/adder_whitebox_test.rs | 6 +-- .../facade/world_tx/scenario_tx_whitebox.rs | 48 +++++++++++++------ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 407f19440f..ee93c7d94b 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -64,7 +64,7 @@ fn adder_whitebox_unified() { .code(CODE_PATH) .new_address(ADDER_ADDRESS) .returns(ReturnsNewBech32Address) - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj, |sc| { sc.init(BigUint::from(3u64)); }); @@ -75,7 +75,7 @@ fn adder_whitebox_unified() { .from(OWNER) .to(ADDER_ADDRESS) .raw_call("") - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj, |sc| { sc.add(BigUint::from(5u64)); }); @@ -84,7 +84,7 @@ fn adder_whitebox_unified() { .to(ADDER_ADDRESS) .raw_call("") .returns(ReturnsRawResult) - .whitebox(adder::contract_obj::(), |sc| { + .whitebox(adder::contract_obj, |sc| { let sum = sc.sum().get(); assert_eq!(sum, BigUint::from(8u64)); }); diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 406e109266..503cfa1d9c 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -1,10 +1,11 @@ use crate::debug_executor::contract_instance_wrapped_execution; use crate::scenario::tx_to_step::TxToQueryStep; -use crate::ScenarioEnvQuery; use crate::{ imports::StaticApi, scenario::tx_to_step::TxToStep, scenario_model::TxResponse, ScenarioEnvExec, }; +use crate::{DebugApi, ScenarioEnvQuery}; use multiversx_chain_vm::tx_mock::TxFunctionName; +use multiversx_sc::contract_base::ContractBase; use multiversx_sc::{ tuple_util::NestedTupleFlatten, types::{ @@ -15,11 +16,10 @@ use multiversx_sc::{ pub trait ScenarioTxWhitebox { type Returns; - fn whitebox( - self, - contract_obj: ContractObj, - f: F, - ) -> Self::Returns; + fn whitebox(self, contract_obj: fn() -> ContractObj, f: F) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj); } impl<'w, From, Payment, CodeValue, RH> ScenarioTxWhitebox @@ -41,11 +41,17 @@ where { type Returns = ::Unpacked; - fn whitebox( + fn whitebox( self, - contract_obj: ContractObj, + contract_obj_builder: fn() -> ContractObj, f: F, - ) -> Self::Returns { + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + let contract_obj = contract_obj_builder(); + let mut step_wrapper = self.tx_to_step(); let (new_address, tx_result) = step_wrapper .env @@ -77,11 +83,17 @@ where { type Returns = ::Unpacked; - fn whitebox( + fn whitebox( self, - contract_obj: ContractObj, + contract_obj_builder: fn() -> ContractObj, f: F, - ) -> Self::Returns { + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + let contract_obj = contract_obj_builder(); + let mut step_wrapper = self.tx_to_step(); // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value @@ -117,11 +129,17 @@ where { type Returns = ::Unpacked; - fn whitebox( + fn whitebox( self, - contract_obj: ContractObj, + contract_obj_builder: fn() -> ContractObj, f: F, - ) -> Self::Returns { + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + let contract_obj = contract_obj_builder(); + let mut step_wrapper = self.tx_to_query_step(); // no endpoint is called per se, but if it is empty, the VM thinks it is a simple transfer of value From b9dd460f5704fc1faeb4bc0d45bbb20e9a4810d4 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 18 Aug 2024 23:40:15 +0300 Subject: [PATCH 12/52] unified syntax - whitebox impl for empty data --- .../adder/tests/adder_whitebox_test.rs | 2 - .../facade/world_tx/scenario_tx_whitebox.rs | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index ee93c7d94b..215f1647d2 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -74,7 +74,6 @@ fn adder_whitebox_unified() { .tx() .from(OWNER) .to(ADDER_ADDRESS) - .raw_call("") .whitebox(adder::contract_obj, |sc| { sc.add(BigUint::from(5u64)); }); @@ -82,7 +81,6 @@ fn adder_whitebox_unified() { let _raw_response = world .query() .to(ADDER_ADDRESS) - .raw_call("") .returns(ReturnsRawResult) .whitebox(adder::contract_obj, |sc| { let sum = sc.sum().get(); diff --git a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs index 503cfa1d9c..62842a6e25 100644 --- a/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs +++ b/framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs @@ -16,6 +16,8 @@ use multiversx_sc::{ pub trait ScenarioTxWhitebox { type Returns; + + /// Runs a lambda function in the name of a smart contract, with the configured transaction context. fn whitebox(self, contract_obj: fn() -> ContractObj, f: F) -> Self::Returns where ContractObj: ContractBase + 'static, @@ -72,6 +74,31 @@ where } } +impl<'w, From, To, Payment, RH> ScenarioTxWhitebox + for Tx, From, To, Payment, (), (), RH> +where + From: TxFromSpecified>, + To: TxToSpecified>, + Payment: TxPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj_builder: fn() -> ContractObj, + f: F, + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + self.raw_call(TxFunctionName::WHITEBOX_CALL.as_str()) + .whitebox(contract_obj_builder, f) + } +} + impl<'w, From, To, Payment, RH> ScenarioTxWhitebox for Tx, From, To, Payment, (), FunctionCall, RH> where @@ -119,6 +146,30 @@ where } } +impl<'w, To, Payment, RH> ScenarioTxWhitebox + for Tx, (), To, Payment, (), (), RH> +where + To: TxToSpecified>, + Payment: TxNoPayment>, + RH: RHListExec>, + RH::ListReturns: NestedTupleFlatten, +{ + type Returns = ::Unpacked; + + fn whitebox( + self, + contract_obj_builder: fn() -> ContractObj, + f: F, + ) -> Self::Returns + where + ContractObj: ContractBase + 'static, + F: FnOnce(ContractObj), + { + self.raw_call(TxFunctionName::WHITEBOX_CALL.as_str()) + .whitebox(contract_obj_builder, f) + } +} + impl<'w, To, Payment, RH> ScenarioTxWhitebox for Tx, (), To, Payment, (), FunctionCall, RH> where From 43a99d8c92286b2e3cfd04fafecf8131b2297005 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Wed, 14 Aug 2024 20:19:29 +0300 Subject: [PATCH 13/52] keystore signing done --- Cargo.lock | 100 +++++++++++++++++++++++++++---- sdk/core/Cargo.toml | 3 + sdk/core/src/data/keystore.rs | 35 +++++++++++ sdk/core/src/data/mod.rs | 1 + sdk/core/src/wallet.rs | 110 ++++++++++++++++++++++++++++++++-- 5 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 sdk/core/src/data/keystore.rs diff --git a/Cargo.lock b/Cargo.lock index 08f2acc6ae..f0558fc8b1 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.11" @@ -197,15 +208,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base64" -version = "0.22.1" +name = "base64ct" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-features" @@ -435,6 +446,16 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.5.11" @@ -670,6 +691,15 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -1527,6 +1557,15 @@ dependencies = [ "serde", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "interact" version = "0.0.0" @@ -1994,7 +2033,7 @@ dependencies = [ name = "multiversx-sc-meta" version = "0.52.3" dependencies = [ - "base64 0.13.1", + "bip39", "clap", "colored", "common-path", @@ -2003,7 +2042,6 @@ dependencies = [ "multiversx-sc", "multiversx-sc-meta-lib", "multiversx-sc-snippets", - "multiversx-sdk", "pathdiff", "reqwest", "ruplacer", @@ -2045,7 +2083,7 @@ dependencies = [ name = "multiversx-sc-scenario" version = "0.52.3" dependencies = [ - "base64 0.22.1", + "base64", "bech32", "colored", "hex", @@ -2069,7 +2107,7 @@ dependencies = [ name = "multiversx-sc-snippets" version = "0.52.3" dependencies = [ - "base64 0.22.1", + "base64", "env_logger", "futures", "hex", @@ -2092,10 +2130,12 @@ dependencies = [ name = "multiversx-sdk" version = "0.5.0" dependencies = [ + "aes", "anyhow", - "base64 0.22.1", + "base64", "bech32", "bip39", + "ctr", "hex", "hmac", "itertools", @@ -2104,6 +2144,7 @@ dependencies = [ "pem", "rand 0.8.5", "reqwest", + "scrypt", "serde", "serde_json", "serde_repr", @@ -2390,6 +2431,17 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "pathdiff" version = "0.2.1" @@ -2423,6 +2475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", + "hmac", ] [[package]] @@ -2431,7 +2484,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.22.1", + "base64", "serde", ] @@ -2763,7 +2816,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "encoding_rs", "futures-channel", @@ -2933,7 +2986,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.1", + "base64", "rustls-pki-types", ] @@ -2960,6 +3013,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -3000,6 +3062,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2 0.10.8", +] + [[package]] name = "second-contract" version = "0.0.0" diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index 463b4ce130..32e170618f 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -35,3 +35,6 @@ bech32 = "0.9" itertools = "0.13.0" pem = "3.0.2" log = "0.4.17" +scrypt = "0.11" +aes = "0.8" +ctr = "0.9.2" \ No newline at end of file diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs new file mode 100644 index 0000000000..fd3a618ce7 --- /dev/null +++ b/sdk/core/src/data/keystore.rs @@ -0,0 +1,35 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CryptoParams { + pub iv: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct KdfParams { + pub dklen: u32, + pub salt: String, + pub n: u32, + pub r: u32, + pub p: u32, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Crypto { + pub ciphertext: String, + pub cipherparams: CryptoParams, + pub cipher: String, + pub kdf: String, + pub kdfparams: KdfParams, + pub mac: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Keystore { + pub version: u32, + pub kind: String, + pub id: String, + pub address: String, + pub bech32: String, + pub crypto: Crypto, +} \ No newline at end of file diff --git a/sdk/core/src/data/mod.rs b/sdk/core/src/data/mod.rs index 797ec6e1ce..9a270211df 100644 --- a/sdk/core/src/data/mod.rs +++ b/sdk/core/src/data/mod.rs @@ -3,6 +3,7 @@ pub mod account_storage; pub mod address; pub mod esdt; pub mod hyperblock; +pub mod keystore; pub mod network_config; pub mod network_economics; pub mod network_status; diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index ab1b0a2f37..0519c0413d 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -1,11 +1,19 @@ extern crate rand; +use std::{ + fs::{self}, + io::{self, Read}, +}; + +use aes::{cipher::KeyIvInit, Aes128}; use anyhow::Result; use bip39::{Language, Mnemonic}; +use ctr::{cipher::StreamCipher, Ctr128BE}; use hmac::{Hmac, Mac}; use pbkdf2::pbkdf2; +use scrypt::{scrypt, Params}; use serde_json::json; -use sha2::{Digest, Sha512}; +use sha2::{Digest, Sha256, Sha512}; use sha3::Keccak256; use zeroize::Zeroize; @@ -14,19 +22,36 @@ use crate::{ private_key::{PrivateKey, PRIVATE_KEY_LENGTH}, public_key::PublicKey, }, - data::{address::Address, transaction::Transaction}, + data::{address::Address, keystore::Keystore, transaction::Transaction}, }; const EGLD_COIN_TYPE: u32 = 508; const HARDENED: u32 = 0x80000000; +const CIPHER_ALGORITHM_AES_128_CTR: &str = "aes-128-ctr"; +const KDF_SCRYPT: &str = "scrypt"; -type HmacSha521 = Hmac; +type HmacSha512 = Hmac; +type HmacSha256 = Hmac; #[derive(Copy, Clone, Debug)] pub struct Wallet { priv_key: PrivateKey, } +#[derive(Clone, Debug)] +pub struct DecryptionParams { + pub derived_key_first_half: Vec, + pub iv: Vec, + pub ciphertext: Vec, +} + +#[derive(Debug)] +pub enum WalletError { + InvalidPassword, + InvalidKdf, + InvalidCipher, +} + impl Wallet { // GenerateMnemonic will generate a new mnemonic value using the bip39 implementation pub fn generate_mnemonic() -> Mnemonic { @@ -63,7 +88,7 @@ impl Wallet { let hardened_child_padding: u8 = 0; let mut digest = - HmacSha521::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); digest.update(&seed); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); let mut key = intermediary[..serialized_key_len].to_vec(); @@ -83,7 +108,7 @@ impl Wallet { buff.push(child_idx as u8); digest = - HmacSha521::new_from_slice(&chain_code).expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(&chain_code).expect("HMAC can take key of any size"); digest.update(&buff); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); key = intermediary[..serialized_key_len].to_vec(); @@ -111,6 +136,15 @@ impl Wallet { Ok(Self { priv_key: pri_key }) } + pub fn from_keystore_secret(file_path: &str) -> Result { + let decyption_params = Self::validate_keystore_password(file_path).unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); + let priv_key = + PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + Ok(Self { priv_key }) + } + pub fn address(&self) -> Address { let public_key = PublicKey::from(&self.priv_key); Address::from(&public_key) @@ -131,4 +165,70 @@ impl Wallet { self.priv_key.sign(tx_bytes) } + + pub fn validate_keystore_password(path: &str) -> Result { + println!( + "Insert password. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done." + ); + let mut password = String::new(); + io::stdin().read_to_string(&mut password).unwrap(); + password = password.trim().to_string(); + + let json_body = fs::read_to_string(path).unwrap(); + let keystore: Keystore = serde_json::from_str(&json_body).unwrap(); + let ciphertext = hex::decode(&keystore.crypto.ciphertext).unwrap(); + + let cipher = &keystore.crypto.cipher; + if cipher != CIPHER_ALGORITHM_AES_128_CTR { + return Err(WalletError::InvalidCipher); + } + + let iv = hex::decode(&keystore.crypto.cipherparams.iv).unwrap(); + let salt = hex::decode(&keystore.crypto.kdfparams.salt).unwrap(); + let json_mac = hex::decode(&keystore.crypto.mac).unwrap(); + + let kdf = &keystore.crypto.kdf; + if kdf != KDF_SCRYPT { + return Err(WalletError::InvalidKdf); + } + let n = keystore.crypto.kdfparams.n as f64; + let r = keystore.crypto.kdfparams.r as u64; + let p = keystore.crypto.kdfparams.p as u64; + let dklen = keystore.crypto.kdfparams.dklen as usize; + + let params = Params::new(n.log2() as u8, r as u32, p as u32, dklen).unwrap(); + + let mut derived_key = vec![0u8; 32]; + scrypt(password.as_bytes(), &salt, ¶ms, &mut derived_key).unwrap(); + + let derived_key_first_half = derived_key[0..16].to_vec(); + let derived_key_second_half = derived_key[16..32].to_vec(); + + let mut input_mac = HmacSha256::new_from_slice(&derived_key_second_half).unwrap(); + input_mac.update(&ciphertext); + let computed_mac = input_mac.finalize().into_bytes(); + + if computed_mac.as_slice() == json_mac.as_slice() { + println!("Password is correct"); + Ok(DecryptionParams { + derived_key_first_half, + iv, + ciphertext, + }) + } else { + println!("Password is incorrect"); + Err(WalletError::InvalidPassword) + } + } + + pub fn decrypt_secret_key(decryption_params: DecryptionParams) -> String { + let mut cipher = Ctr128BE::::new( + decryption_params.derived_key_first_half.as_slice().into(), + decryption_params.iv.as_slice().into(), + ); + let mut decrypted = decryption_params.ciphertext.to_vec(); + cipher.apply_keystream(&mut decrypted); + + hex::encode(decrypted).to_string() + } } From 695f622fc4b3aaab4f3d66964ec51ce5d942dd46 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 19 Aug 2024 20:32:53 +0200 Subject: [PATCH 14/52] whitebox migration to unified for adder, scenario tester and staking module --- .../adder/tests/adder_whitebox_test.rs | 39 -- .../scenario-tester/tests/st_whitebox_test.rs | 64 +- .../tests/staking_module_whitebox_test.rs | 659 ++++++++---------- 3 files changed, 321 insertions(+), 441 deletions(-) diff --git a/contracts/examples/adder/tests/adder_whitebox_test.rs b/contracts/examples/adder/tests/adder_whitebox_test.rs index 215f1647d2..c609b08302 100644 --- a/contracts/examples/adder/tests/adder_whitebox_test.rs +++ b/contracts/examples/adder/tests/adder_whitebox_test.rs @@ -1,7 +1,6 @@ use adder::*; use multiversx_sc_scenario::imports::*; -const ADDER_PATH_EXPR: &str = "mxsc:output/adder.mxsc.json"; const OWNER: TestAddress = TestAddress::new("owner"); const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); const CODE_PATH: MxscPath = MxscPath::new("mxsc:output/adder.mxsc.json"); @@ -16,44 +15,6 @@ fn world() -> ScenarioWorld { #[test] fn adder_whitebox() { let mut world = world(); - let adder_whitebox = WhiteboxContract::new("sc:adder", adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - - world - .set_state_step( - SetStateStep::new() - .put_account("address:owner", Account::new().nonce(1)) - .new_address("address:owner", 1, "sc:adder"), - ) - .whitebox_deploy( - &adder_whitebox, - ScDeployStep::new().from("address:owner").code(adder_code), - |sc| { - sc.init(5u32.into()); - }, - ) - .whitebox_query(&adder_whitebox, |sc| { - let sum_value = sc.sum(); - assert_eq!(sum_value.get(), 5u32); - }) - .whitebox_call( - &adder_whitebox, - ScCallStep::new().from("address:owner"), - |sc| sc.add(3u32.into()), - ) - .check_state_step( - CheckStateStep::new() - .put_account("address:owner", CheckAccount::new()) - .put_account( - "sc:adder", - CheckAccount::new().check_storage("str:sum", "8"), - ), - ); -} - -#[test] -fn adder_whitebox_unified() { - let mut world = world(); world.account(OWNER).nonce(1); diff --git a/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs b/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs index a6318b1f7f..61dd6cdc2d 100644 --- a/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs +++ b/contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs @@ -1,7 +1,9 @@ use multiversx_sc_scenario::imports::*; use scenario_tester::*; -const ADDER_PATH_EXPR: &str = "mxsc:output/scenario-tester.mxsc.json"; +const ST_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/scenario-tester.mxsc.json"); +const OWNER: TestAddress = TestAddress::new("owner"); +const SCENARIO_TESTER: TestSCAddress = TestSCAddress::new("scenario-tester"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -16,37 +18,37 @@ fn world() -> ScenarioWorld { #[test] fn st_whitebox() { let mut world = world(); - let st_whitebox = WhiteboxContract::new("sc:adder", scenario_tester::contract_obj); - let st_code = world.code_expression(ADDER_PATH_EXPR); + + world.account(OWNER).nonce(1); + + let new_address = world + .tx() + .from(OWNER) + .raw_deploy() + .code(ST_PATH_EXPR) + .new_address(SCENARIO_TESTER) + .returns(ReturnsNewBech32Address) + .whitebox(scenario_tester::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); + + assert_eq!(new_address.to_address(), SCENARIO_TESTER.to_address()); world - .set_state_step( - SetStateStep::new() - .put_account("address:owner", Account::new().nonce(1)) - .new_address("address:owner", 1, "sc:adder"), - ) - .whitebox_deploy( - &st_whitebox, - ScDeployStep::new().from("address:owner").code(st_code), - |sc| { - sc.init(5u32.into()); - }, - ) - .whitebox_query(&st_whitebox, |sc| { + .query() + .to(SCENARIO_TESTER) + .whitebox(scenario_tester::contract_obj, |sc| { let sum_value = sc.sum(); - assert_eq!(sum_value.get(), 5u32); - }) - .whitebox_call( - &st_whitebox, - ScCallStep::new().from("address:owner"), - |sc| sc.add(3u32.into()), - ) - .check_state_step( - CheckStateStep::new() - .put_account("address:owner", CheckAccount::new()) - .put_account( - "sc:adder", - CheckAccount::new().check_storage("str:sum", "8"), - ), - ); + assert_eq!(sum_value.get(), BigUint::from(5u32)); + }); + + world + .tx() + .from(OWNER) + .to(SCENARIO_TESTER) + .whitebox(scenario_tester::contract_obj, |sc| sc.add(3u32.into())); + + world + .check_account(SCENARIO_TESTER) + .check_storage("str:sum", "8"); } diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs index 612fa725df..0f705ad131 100644 --- a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -1,23 +1,23 @@ use multiversx_sc_modules::staking::StakingModule; use multiversx_sc_scenario::imports::*; -const STAKING_TOKEN_ID_EXPR: &str = "str:STAKE-123456"; +const STAKING_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("STAKE-123456"); const STAKING_TOKEN_ID: &[u8] = b"STAKE-123456"; const INITIAL_BALANCE: u64 = 2_000_000; const REQUIRED_STAKE_AMOUNT: u64 = 1_000_000; const SLASH_AMOUNT: u64 = 600_000; const QUORUM: usize = 3; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const ALICE_ADDRESS_EXPR: &str = "address:alice"; -const BOB_ADDRESS_EXPR: &str = "address:bob"; -const CAROL_ADDRESS_EXPR: &str = "address:carol"; -const EVE_ADDRESS_EXPR: &str = "address:eve"; -const PAUL_ADDRESS_EXPR: &str = "address:paul"; -const SALLY_ADDRESS_EXPR: &str = "address:sally"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const ALICE_ADDRESS: TestAddress = TestAddress::new("alice"); +const BOB_ADDRESS: TestAddress = TestAddress::new("bob"); +const CAROL_ADDRESS: TestAddress = TestAddress::new("carol"); +const EVE_ADDRESS: TestAddress = TestAddress::new("eve"); +const PAUL_ADDRESS: TestAddress = TestAddress::new("paul"); +const SALLY_ADDRESS: TestAddress = TestAddress::new("sally"); -const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; -const USE_MODULE_PATH_EXPR: &str = "mxsc:output/use-module.mxsc.json"; +const USE_MODULE_ADDRESS: TestSCAddress = TestSCAddress::new("use-module"); +const USE_MODULE_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/use-module.mxsc.json"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -30,447 +30,364 @@ fn world() -> ScenarioWorld { fn test_staking_module() { let mut world = world(); - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(OWNER_ADDRESS_EXPR, 1, USE_MODULE_ADDRESS_EXPR) - .put_account( - ALICE_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - BOB_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - CAROL_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - EVE_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - PAUL_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ) - .put_account( - SALLY_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE), - ), - ); + world.account(OWNER_ADDRESS).nonce(1); + world + .account(ALICE_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(BOB_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(CAROL_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(EVE_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(PAUL_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + world + .account(SALLY_ADDRESS) + .nonce(1) + .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); // init - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); - - world.whitebox_deploy( - &use_module_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(use_module_code), - |sc| { + let new_address = world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(USE_MODULE_PATH_EXPR) + .new_address(USE_MODULE_ADDRESS) + .returns(ReturnsNewBech32Address) + .whitebox(use_module::contract_obj, |sc| { let mut whitelist = ManagedVec::new(); - whitelist.push(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - whitelist.push(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))); - whitelist.push(managed_address!(&address_expr_to_address( - CAROL_ADDRESS_EXPR - ))); - whitelist.push(managed_address!(&address_expr_to_address( - PAUL_ADDRESS_EXPR - ))); - whitelist.push(managed_address!(&address_expr_to_address( - SALLY_ADDRESS_EXPR - ))); + whitelist.push(ALICE_ADDRESS.to_managed_address()); + whitelist.push(BOB_ADDRESS.to_managed_address()); + whitelist.push(CAROL_ADDRESS.to_managed_address()); + whitelist.push(PAUL_ADDRESS.to_managed_address()); + whitelist.push(SALLY_ADDRESS.to_managed_address()); sc.init_staking_module( - &EgldOrEsdtTokenIdentifier::esdt(managed_token_id!(STAKING_TOKEN_ID)), - &managed_biguint!(REQUIRED_STAKE_AMOUNT), - &managed_biguint!(SLASH_AMOUNT), + &EgldOrEsdtTokenIdentifier::esdt(STAKING_TOKEN_ID), + &BigUint::from(REQUIRED_STAKE_AMOUNT), + &BigUint::from(SLASH_AMOUNT), QUORUM, &whitelist, ); - }, - ); + }); + + assert_eq!(new_address.to_address(), USE_MODULE_ADDRESS.to_address()); // try stake - not a board member - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new() - .from(EVE_ADDRESS_EXPR) - .esdt_transfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT) - .no_expect(), - |sc| sc.stake(), - |r| { - r.assert_user_error("Only whitelisted members can stake"); - }, - ); + world + .tx() + .from(EVE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), + 0, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .returns(ExpectError(4u64, "Only whitelisted members can stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); // stake half and try unstake - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), 0, - REQUIRED_STAKE_AMOUNT / 2, - ), - |sc| sc.stake(), - ); + &BigUint::from(REQUIRED_STAKE_AMOUNT / 2), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), - |sc| sc.unstake(managed_biguint!(REQUIRED_STAKE_AMOUNT / 4)), - |r| { - r.assert_user_error("Not enough stake"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(REQUIRED_STAKE_AMOUNT / 4)); + }); // bob and carol stake - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(BOB_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(CAROL_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); + + world + .tx() + .from(CAROL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(PAUL_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); + + world + .tx() + .from(PAUL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SALLY_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); + + world + .tx() + .from(SALLY_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| sc.stake(), - ); + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.stake(); + }); // try vote slash, not enough stake - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), - |sc| sc.vote_slash_member(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))), - |r| { - r.assert_user_error("Not enough stake"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(BOB_ADDRESS.to_managed_address()); + }); // try vote slash, slashed address not a board member - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), - |sc| sc.vote_slash_member(managed_address!(&address_expr_to_address(EVE_ADDRESS_EXPR))), - |r| { - r.assert_user_error("Voted user is not a staked board member"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Voted user is not a staked board member")) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(EVE_ADDRESS.to_managed_address()); + }); // alice stake over max amount and withdraw surplus - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).esdt_transfer( - STAKING_TOKEN_ID, + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), 0, - REQUIRED_STAKE_AMOUNT, - ), - |sc| { + &BigUint::from(REQUIRED_STAKE_AMOUNT), + ) + .whitebox(use_module::contract_obj, |sc| { sc.stake(); - let alice_staked_amount = sc - .staked_amount(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .get(); - assert_eq!(alice_staked_amount, managed_biguint!(1_500_000)); - }, - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR), - |sc| { - sc.unstake(managed_biguint!(500_000)); - - let alice_staked_amount = sc - .staked_amount(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .get(); - assert_eq!(alice_staked_amount, managed_biguint!(1_000_000)); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - ALICE_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, "1_000_000"), - )); + let alice_staked_amount = sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(); + assert_eq!(alice_staked_amount, BigUint::from(1_500_000u64)); + }); + + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(500_000u64)); + let alice_staked_amount = sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(); + assert_eq!(alice_staked_amount, BigUint::from(1_000_000u64)); + }); + + world + .check_account(ALICE_ADDRESS) + .esdt_balance(STAKING_TOKEN_ID_EXPR, BigUint::from(1_000_000u64)); // alice vote to slash bob - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(BOB_ADDRESS.to_managed_address()); assert_eq!( - sc.slashing_proposal_voters(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - ))) - .len(), + sc.slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) + .len(), 1 ); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - )))); - }, - ); + .slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) + .contains(&ALICE_ADDRESS.to_managed_address())); + }); // bob vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(BOB_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // try slash before quorum reached - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(BOB_ADDRESS_EXPR).no_expect(), - |sc| { - sc.slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - |r| { - r.assert_user_error("Quorum not reached"); - }, - ); + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Quorum not reached")) + .whitebox(use_module::contract_obj, |sc| { + sc.slash_member(ALICE_ADDRESS.to_managed_address()); + }); // paul vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(PAUL_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(PAUL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // sally vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SALLY_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(SALLY_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // sally cancels vote to slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SALLY_ADDRESS_EXPR), - |sc| { - sc.cancel_vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); - }, - ); + world + .tx() + .from(SALLY_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.cancel_vote_slash_member(ALICE_ADDRESS.to_managed_address()); + }); // carol vote - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(CAROL_ADDRESS_EXPR), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); + world + .tx() + .from(CAROL_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(ALICE_ADDRESS.to_managed_address()); assert_eq!( - sc.slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .len(), + sc.slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .len(), 3 ); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&BOB_ADDRESS.to_managed_address())); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - CAROL_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&CAROL_ADDRESS.to_managed_address())); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - PAUL_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&PAUL_ADDRESS.to_managed_address())); assert!(!sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - SALLY_ADDRESS_EXPR - )))); - }, - ); + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) + .contains(&SALLY_ADDRESS.to_managed_address())); + }); // slash alice - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(BOB_ADDRESS_EXPR), - |sc| { - sc.slash_member(managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); + world + .tx() + .from(BOB_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.slash_member(ALICE_ADDRESS.to_managed_address()); assert_eq!( - sc.staked_amount(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) - .get(), - managed_biguint!(REQUIRED_STAKE_AMOUNT - SLASH_AMOUNT) - ); - assert_eq!( - sc.total_slashed_amount().get(), - managed_biguint!(SLASH_AMOUNT) + sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(), + BigUint::from(REQUIRED_STAKE_AMOUNT - SLASH_AMOUNT) ); + assert_eq!(sc.total_slashed_amount().get(), BigUint::from(SLASH_AMOUNT)); assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))) + .slashing_proposal_voters(&ALICE_ADDRESS.to_managed_address()) .is_empty()); - }, - ); + }); // alice try vote after slash - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), - |sc| { - sc.vote_slash_member(managed_address!(&address_expr_to_address(BOB_ADDRESS_EXPR))); - }, - |r| { - r.assert_user_error("Not enough stake"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.vote_slash_member(BOB_ADDRESS.to_managed_address()); + }); // alice try unstake the remaining tokens - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR).no_expect(), - |sc| { - sc.unstake(managed_biguint!(400_000)); - }, - |r| { - r.assert_user_error("Not enough stake"); - }, - ); + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Not enough stake")) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(400_000u64)); + }); // alice remove from board members - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { // check alice's votes before slash assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - ))) - .contains(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - )))); + .slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) + .contains(&ALICE_ADDRESS.to_managed_address())); - sc.remove_board_member(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - ))); + sc.remove_board_member(&ALICE_ADDRESS.to_managed_address()); assert_eq!(sc.user_whitelist().len(), 4); assert!(!sc .user_whitelist() - .contains(&managed_address!(&address_expr_to_address( - ALICE_ADDRESS_EXPR - )))); + .contains(&ALICE_ADDRESS.to_managed_address())); // alice's vote gets removed assert!(sc - .slashing_proposal_voters(&managed_address!(&address_expr_to_address( - BOB_ADDRESS_EXPR - ))) + .slashing_proposal_voters(&BOB_ADDRESS.to_managed_address()) .is_empty()); - }, - ); + }); // alice unstake ok - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(ALICE_ADDRESS_EXPR), - |sc| { - sc.unstake(managed_biguint!(400_000)); - }, + world + .tx() + .from(ALICE_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + sc.unstake(BigUint::from(400_000u64)); + }); + + world.check_account(ALICE_ADDRESS).esdt_balance( + TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), + BigUint::from(INITIAL_BALANCE - SLASH_AMOUNT), ); - - world.check_state_step(CheckStateStep::new().put_account( - ALICE_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE - SLASH_AMOUNT), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() } From a8f137726086ac070135d01b1e81964deee12455 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 20 Aug 2024 09:09:06 +0300 Subject: [PATCH 15/52] upgrade blackbox rust_testing_framework_tester --- .../sc-config.toml | 5 ++ .../src/dummy_module.rs | 2 - .../rust-testing-framework-tester/src/lib.rs | 7 +- .../rust_testing_framework_tester_proxy.rs | 61 +++++++++++++ .../tests/tester_blackbox_test.rs | 85 +++++++------------ 5 files changed, 99 insertions(+), 61 deletions(-) create mode 100644 contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs diff --git a/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml b/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml index 330cdda658..b8c5b739dc 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml +++ b/contracts/feature-tests/rust-testing-framework-tester/sc-config.toml @@ -4,3 +4,8 @@ main = "rust-testing-framework-tester" # the only purpose of this config is to specify the allocator [contracts.rust-testing-framework-tester] allocator = "static64k" + +[[proxy]] +path = "src/rust_testing_framework_tester_proxy.rs" +add-unlabelled = false +add-endpoints = ["init"] diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs b/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs index 76721a8fc4..7db5c9379d 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/dummy_module.rs @@ -1,5 +1,3 @@ -multiversx_sc::imports!(); - #[multiversx_sc::module] pub trait DummyModule { fn some_function(&self) -> BigUint { diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs index 4133f3f039..ad3766e123 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs @@ -1,11 +1,12 @@ #![no_std] -multiversx_sc::imports!(); -multiversx_sc::derive_imports!(); +use multiversx_sc::proxy_imports::*; pub mod dummy_module; +pub mod rust_testing_framework_tester_proxy; -#[derive(TopEncode, TopDecode, TypeAbi, Clone, Debug, PartialEq, Eq)] +#[type_abi] +#[derive(TopEncode, TopDecode, Clone, Debug, PartialEq, Eq)] pub struct NftDummyAttributes { pub creation_epoch: u64, pub cool_factor: u8, diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs b/contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs new file mode 100644 index 0000000000..6a42d7e5b3 --- /dev/null +++ b/contracts/feature-tests/rust-testing-framework-tester/src/rust_testing_framework_tester_proxy.rs @@ -0,0 +1,61 @@ +// 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 RustTestingFrameworkTesterProxy; + +impl TxProxyTrait for RustTestingFrameworkTesterProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = RustTestingFrameworkTesterProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + RustTestingFrameworkTesterProxyMethods { wrapped_tx: tx } + } +} + +pub struct RustTestingFrameworkTesterProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl RustTestingFrameworkTesterProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init( + self, + ) -> TxTypedDeploy> { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .original_result() + } +} + +#[type_abi] +#[derive(TopEncode, TopDecode, Clone, Debug, PartialEq, Eq)] +pub struct NftDummyAttributes { + pub creation_epoch: u64, + pub cool_factor: u8, +} diff --git a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs index afdabb5199..fe4e7f5b77 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs @@ -1,77 +1,50 @@ use multiversx_sc_scenario::imports::*; use rust_testing_framework_tester::*; -const WASM_PATH_EXPR: &str = "mxsc:output/rust-testing-framework-tester.mxsc.json"; +const CODE_PATH: MxscPath = MxscPath::new("output/rust-testing-framework-tester.mxsc.json"); +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const RUST_TESTING_FRAMEWORK_TESTER_ADDRESS: TestSCAddress = + TestSCAddress::new("rust-testing-framework-tester"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract( - WASM_PATH_EXPR, - rust_testing_framework_tester::ContractBuilder, - ); + blockchain.register_contract(CODE_PATH, rust_testing_framework_tester::ContractBuilder); + blockchain } #[test] -#[allow(deprecated)] fn tester_deploy_test() { let mut world = world(); - let code = world.code_expression(WASM_PATH_EXPR); - let owner_address = "address:owner"; - let mut adder_contract = - ContractInfo::>::new("sc:contract"); + world.start_trace(); + + world.account(OWNER_ADDRESS).new_address( + OWNER_ADDRESS, + 0, + RUST_TESTING_FRAMEWORK_TESTER_ADDRESS, + ); - world - .start_trace() - .set_state_step( - SetStateStep::new() - .put_account(owner_address, Account::new()) - .new_address(owner_address, 0, &adder_contract), - ) - .sc_deploy_use_result( - ScDeployStep::new() - .from(owner_address) - .code(code) - .call(adder_contract.init()), - |address, tr: TypedResponse| { - assert_eq!(address, adder_contract.to_address()); - assert_eq!(tr.result.unwrap(), "constructor-result"); - }, - ) - .write_scenario_trace("scenarios/trace-deploy.scen.json"); + let (returned_value, contract_address) = world + .tx() + .from(OWNER_ADDRESS) + .typed(rust_testing_framework_tester_proxy::RustTestingFrameworkTesterProxy) + .init() + .code(CODE_PATH) + .returns(ReturnsResult) + .new_address(RUST_TESTING_FRAMEWORK_TESTER_ADDRESS) + .returns(ReturnsNewAddress) + .run(); + + assert_eq!(returned_value.to_string(), "constructor-result"); + assert_eq!(contract_address, RUST_TESTING_FRAMEWORK_TESTER_ADDRESS); + + world.write_scenario_trace("scenarios/trace-deploy.scen.json"); } #[test] -#[allow(deprecated)] fn tester_deploy_test_spawned_thread() { - let handler = std::thread::spawn(|| { - let mut world = world(); - let code = world.code_expression(WASM_PATH_EXPR); - - let owner_address = "address:owner"; - let mut adder_contract = - ContractInfo::>::new("sc:contract"); - - world - .start_trace() - .set_state_step( - SetStateStep::new() - .put_account(owner_address, Account::new()) - .new_address(owner_address, 0, &adder_contract), - ) - .sc_deploy_use_result( - ScDeployStep::new() - .from(owner_address) - .code(code) - .call(adder_contract.init()), - |address, tr: TypedResponse| { - assert_eq!(address, adder_contract.to_address()); - assert_eq!(tr.result.unwrap(), "constructor-result"); - }, - ) - .write_scenario_trace("scenarios/trace-deploy.scen.json"); - }); + let handler = std::thread::spawn(|| tester_deploy_test()); handler.join().unwrap(); } From 2d508a9e0cba4535b550455bd4d555c040f6be57 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 20 Aug 2024 10:09:10 +0300 Subject: [PATCH 16/52] fix clippy --- .../rust-testing-framework-tester/tests/tester_blackbox_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs index fe4e7f5b77..a426721718 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/tests/tester_blackbox_test.rs @@ -44,7 +44,7 @@ fn tester_deploy_test() { #[test] fn tester_deploy_test_spawned_thread() { - let handler = std::thread::spawn(|| tester_deploy_test()); + let handler = std::thread::spawn(tester_deploy_test); handler.join().unwrap(); } From 0490e8122b385d6b4e6ff8d5b3ed0c60cd711b0f Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Tue, 20 Aug 2024 10:40:24 +0300 Subject: [PATCH 17/52] password prompt separated --- sdk/core/src/data/keystore.rs | 15 ++++++++++- sdk/core/src/wallet.rs | 47 +++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs index fd3a618ce7..2564d70a2e 100644 --- a/sdk/core/src/data/keystore.rs +++ b/sdk/core/src/data/keystore.rs @@ -1,5 +1,11 @@ use serde::{Deserialize, Serialize}; +#[derive(Debug)] +pub enum WalletError { + InvalidPassword, + InvalidKdf, + InvalidCipher, +} #[derive(Debug, Serialize, Deserialize)] pub struct CryptoParams { pub iv: String, @@ -32,4 +38,11 @@ pub struct Keystore { pub address: String, pub bech32: String, pub crypto: Crypto, -} \ No newline at end of file +} + +#[derive(Clone, Debug)] +pub struct DecryptionParams { + pub derived_key_first_half: Vec, + pub iv: Vec, + pub ciphertext: Vec, +} diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index 0519c0413d..b2856b74da 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -22,7 +22,11 @@ use crate::{ private_key::{PrivateKey, PRIVATE_KEY_LENGTH}, public_key::PublicKey, }, - data::{address::Address, keystore::Keystore, transaction::Transaction}, + data::{ + address::Address, + keystore::{DecryptionParams, Keystore, WalletError}, + transaction::Transaction, + }, }; const EGLD_COIN_TYPE: u32 = 508; @@ -38,20 +42,6 @@ pub struct Wallet { priv_key: PrivateKey, } -#[derive(Clone, Debug)] -pub struct DecryptionParams { - pub derived_key_first_half: Vec, - pub iv: Vec, - pub ciphertext: Vec, -} - -#[derive(Debug)] -pub enum WalletError { - InvalidPassword, - InvalidKdf, - InvalidCipher, -} - impl Wallet { // GenerateMnemonic will generate a new mnemonic value using the bip39 implementation pub fn generate_mnemonic() -> Mnemonic { @@ -137,14 +127,27 @@ impl Wallet { } pub fn from_keystore_secret(file_path: &str) -> Result { - let decyption_params = Self::validate_keystore_password(file_path).unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); + let decyption_params = + Self::validate_keystore_password(file_path, Self::get_keystore_password()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); let priv_key = PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; Ok(Self { priv_key }) } + pub fn get_private_key_from_keystore_secret(file_path: &str) -> Result { + let decyption_params = + Self::validate_keystore_password(file_path, Self::get_keystore_password()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); + let priv_key = + PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + Ok(priv_key) + } + pub fn address(&self) -> Address { let public_key = PublicKey::from(&self.priv_key); Address::from(&public_key) @@ -166,14 +169,20 @@ impl Wallet { self.priv_key.sign(tx_bytes) } - pub fn validate_keystore_password(path: &str) -> Result { + fn get_keystore_password() -> String { println!( "Insert password. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done." ); let mut password = String::new(); io::stdin().read_to_string(&mut password).unwrap(); password = password.trim().to_string(); + password + } + pub fn validate_keystore_password( + path: &str, + password: String, + ) -> Result { let json_body = fs::read_to_string(path).unwrap(); let keystore: Keystore = serde_json::from_str(&json_body).unwrap(); let ciphertext = hex::decode(&keystore.crypto.ciphertext).unwrap(); From c1b54c1d8c2b9e9683d84431623e0338d78cdbd8 Mon Sep 17 00:00:00 2001 From: JustEatAnApple Date: Wed, 21 Aug 2024 20:31:47 +0300 Subject: [PATCH 18/52] Keystore <-> Pem Sc-meta --- Cargo.lock | 10 ++ framework/meta/src/cmd/wallet.rs | 147 +++++++++++++++++----------- framework/meta/tests/wallet_test.rs | 91 +++++++++++++++++ sdk/core/Cargo.toml | 3 +- sdk/core/src/data/keystore.rs | 8 +- sdk/core/src/wallet.rs | 137 +++++++++++++++++++++----- 6 files changed, 316 insertions(+), 80 deletions(-) create mode 100644 framework/meta/tests/wallet_test.rs diff --git a/Cargo.lock b/Cargo.lock index f0558fc8b1..fecbf652fe 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -2151,6 +2151,7 @@ dependencies = [ "sha2 0.10.8", "sha3", "tokio", + "uuid", "zeroize", ] @@ -3724,6 +3725,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom 0.2.15", +] + [[package]] name = "vault" version = "0.0.0" diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index 7fcf28899a..ba8a9f6132 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -1,16 +1,16 @@ use core::str; -use multiversx_sc::types; -use std::{ - fs::{self, File}, - io::{self, Read, Write}, -}; use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; -use bip39::Mnemonic; +use multiversx_sc::types::{self}; use multiversx_sc_snippets::sdk::{ crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, }; use multiversx_sc_snippets::{hex, imports::Bech32Address}; +use std::{ + fs::{self, File}, + io::{self, Read, Write}, +}; + pub fn wallet(args: &WalletArgs) { let command = &args.command; match command { @@ -27,45 +27,92 @@ fn convert(convert_args: &WalletConvertArgs) { let out_format = &convert_args.to; let mut mnemonic_str = String::new(); + let private_key_str: String; + let public_key_str: String; match (in_format.as_str(), out_format.as_str()) { ("mnemonic", "pem") => match infile { Some(file) => { mnemonic_str = fs::read_to_string(file).unwrap(); - mnemonic_str = mnemonic_str.replace('\n', ""); + (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic_str); + write_resulted_pem(&public_key_str, &private_key_str, outfile); }, None => { println!("Insert text below. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done."); - _ = io::stdin().read_to_string(&mut mnemonic_str).unwrap() + _ = io::stdin().read_to_string(&mut mnemonic_str).unwrap(); + (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic_str); + write_resulted_pem(&public_key_str, &private_key_str, outfile); + }, + }, + ("keystore-secret", "pem") => match infile { + Some(file) => { + let private_key = Wallet::get_private_key_from_keystore_secret( + file, + &Wallet::get_keystore_password(), + ) + .unwrap(); + private_key_str = private_key.to_string(); + let public_key = PublicKey::from(&private_key); + public_key_str = public_key.to_string(); + write_resulted_pem(&public_key_str, &private_key_str, outfile); + }, + None => { + panic!("Input file is required for keystore-secret format"); + }, + }, + ("pem", "keystore-secret") => match infile { + Some(file) => { + let pem_decoded_keys = Wallet::get_pem_decoded_content(file); + (private_key_str, public_key_str) = Wallet::get_wallet_keys_pem(file); + + let address = get_wallet_address(&private_key_str); + let hex_decoded_keys = hex::decode(pem_decoded_keys).unwrap(); + + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + &Wallet::get_keystore_password(), + ); + write_resulted_keystore(json_result, outfile); + }, + None => { + panic!("Input file is required for pem format"); }, }, _ => { println!("Unsupported conversion"); }, } +} - let mnemonic = Mnemonic::parse(mnemonic_str).unwrap(); - - let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); - let address = get_wallet_address(private_key_str.as_str()); - +fn write_resulted_pem(public_key: &str, private_key: &str, outfile: Option<&String>) { + let address = get_wallet_address(private_key); match outfile { Some(outfile) => { - generate_pem( - &address, - private_key_str.as_str(), - public_key_str.as_str(), - outfile, - ); + let pem_content = generate_pem_content(&address, private_key, public_key); + let mut file = File::create(outfile).unwrap(); + file.write_all(pem_content.as_bytes()).unwrap(); }, None => { - let pem_content = - generate_pem_content(&address, private_key_str.as_str(), public_key_str.as_str()); + let pem_content = generate_pem_content(&address, private_key, public_key); print!("{}", pem_content); }, } } +fn write_resulted_keystore(json_result: String, outfile: Option<&String>) { + match outfile { + Some(outfile) => { + let mut file = File::create(outfile).unwrap(); + file.write_all(json_result.as_bytes()).unwrap(); + }, + None => { + println!("{}", json_result); + }, + } +} + fn bech32_conversion(bech32_args: &WalletBech32Args) { let encode_address = bech32_args.hex_address.as_ref(); let decode_address = bech32_args.bech32_address.as_ref(); @@ -90,57 +137,45 @@ fn bech32_conversion(bech32_args: &WalletBech32Args) { } } -fn get_wallet_keys(mnemonic: Mnemonic) -> (String, String) { - let private_key = Wallet::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); - let public_key = PublicKey::from(&private_key); - - let public_key_str: &str = &public_key.to_string(); - let private_key_str: &str = &private_key.to_string(); - - (private_key_str.to_string(), public_key_str.to_string()) -} - fn get_wallet_address(private_key: &str) -> Address { let wallet = Wallet::from_private_key(private_key).unwrap(); wallet.address() } fn new(new_args: &WalletNewArgs) { - let format = new_args.wallet_format.as_ref(); - let outfile = new_args.outfile.as_ref(); + let format = new_args.wallet_format.as_deref(); + let outfile = new_args.outfile.as_ref(); // Handle outfile as Option<&str> if it's an Option let mnemonic = Wallet::generate_mnemonic(); println!("Mnemonic: {}", mnemonic); - let (private_key_str, public_key_str) = get_wallet_keys(mnemonic); + let (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic.to_string()); let address = get_wallet_address(private_key_str.as_str()); println!("Wallet address: {}", address); - if let Some(f) = format { - match (f.as_str(), outfile) { - ("pem", Some(file)) => { - generate_pem( - &address, - private_key_str.as_str(), - public_key_str.as_str(), - file, - ); - }, - ("pem", None) => { - println!("Output file is required for PEM format"); - }, - _ => {}, - } + match format { + Some("pem") => { + write_resulted_pem(public_key_str.as_str(), private_key_str.as_str(), outfile); + }, + Some("keystore-secret") => { + let concatenated_keys = format!("{}{}", private_key_str, public_key_str); + let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + &Wallet::get_keystore_password(), + ); + write_resulted_keystore(json_result, outfile); + }, + Some(_) => { + println!("Unsupported format"); + }, + None => {}, } } -fn generate_pem(address: &Address, private_key: &str, public_key: &str, outfile: &String) { - let pem_content = generate_pem_content(address, private_key, public_key); - let mut file = File::create(outfile).unwrap(); - file.write_all(pem_content.as_bytes()).unwrap() -} - -fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { +pub fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { let concat_keys = format!("{}{}", private_key, public_key); let concat_keys_b64 = base64_encode(concat_keys); diff --git a/framework/meta/tests/wallet_test.rs b/framework/meta/tests/wallet_test.rs new file mode 100644 index 0000000000..ce1627ff64 --- /dev/null +++ b/framework/meta/tests/wallet_test.rs @@ -0,0 +1,91 @@ +use std::fs::{self, File}; +use std::io::Write; + +use multiversx_sc_meta::cmd::wallet::generate_pem_content; +use multiversx_sc_snippets::sdk::{crypto::public_key::PublicKey, data::address::Address}; +use multiversx_sc_snippets::{hex, imports::Wallet}; + +const ALICE_PEM_PATH: &str = "../snippets/src/test_wallets/alice.pem"; +const ALICE_KEYSTORE_PATH_TEST: &str = "alice.json"; +const ALICE_PEM_PATH_TEST: &str = "alice_test.pem"; +const KEYSTORE_PASSWORD: &str = "abcd"; + +fn create_keystore_from_pem(file: &str) { + let pem_decoded_keys = Wallet::get_pem_decoded_content(file); + let (private_key_str, public_key_str) = Wallet::get_wallet_keys_pem(file); + + let address = Wallet::from_private_key(&private_key_str) + .unwrap() + .address(); + let hex_decoded_keys = hex::decode(pem_decoded_keys).unwrap(); + + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + KEYSTORE_PASSWORD, + ); + + write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); +} + +fn write_to_file(content: &str, file: &str) { + let mut file = File::create(file).unwrap(); + file.write_all(content.as_bytes()).unwrap(); +} + +fn create_keystore_file_from_scratch() -> Address { + let mnemonic = Wallet::generate_mnemonic(); + let (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic.to_string()); + let wallet = Wallet::from_private_key(&private_key_str).unwrap(); + let address = wallet.address(); + + let concatenated_keys = format!("{}{}", private_key_str, public_key_str); + let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + &public_key_str, + KEYSTORE_PASSWORD, + ); + write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); + address +} + +#[test] +fn test_wallet_convert_pem_to_keystore() { + create_keystore_from_pem(ALICE_PEM_PATH); + let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); + assert_eq!( + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap() + .to_string(), + private_key_pem + ); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} + +#[test] +fn test_wallet_convert_keystore_to_pem() { + let address = create_keystore_file_from_scratch(); + + let private_key = + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap(); + let private_key_str = private_key.to_string(); + let public_key = PublicKey::from(&private_key); + let public_key_str = public_key.to_string(); + + let pem_content = generate_pem_content(&address, &private_key_str, &public_key_str); + write_to_file(&pem_content, ALICE_PEM_PATH_TEST); + + assert_eq!( + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap() + .to_string(), + Wallet::get_wallet_keys_pem(ALICE_PEM_PATH_TEST).0 + ); + + fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index 32e170618f..e84f8cd4cb 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -37,4 +37,5 @@ pem = "3.0.2" log = "0.4.17" scrypt = "0.11" aes = "0.8" -ctr = "0.9.2" \ No newline at end of file +ctr = "0.9.2" +uuid = {version = "1.10.0", features = ["v4"]} \ No newline at end of file diff --git a/sdk/core/src/data/keystore.rs b/sdk/core/src/data/keystore.rs index 2564d70a2e..1b3c656ef1 100644 --- a/sdk/core/src/data/keystore.rs +++ b/sdk/core/src/data/keystore.rs @@ -1,5 +1,11 @@ use serde::{Deserialize, Serialize}; +pub const KDF_N: u32 = 4096; +pub const KDF_R: u32 = 8; +pub const KDF_P: u32 = 1; +pub const KDF_DKLEN: usize = 32; +pub const KEYSTORE_VERSION: u32 = 4; + #[derive(Debug)] pub enum WalletError { InvalidPassword, @@ -44,5 +50,5 @@ pub struct Keystore { pub struct DecryptionParams { pub derived_key_first_half: Vec, pub iv: Vec, - pub ciphertext: Vec, + pub data: Vec, } diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index b2856b74da..bbf2c41a2c 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -1,5 +1,6 @@ extern crate rand; +use core::str; use std::{ fs::{self}, io::{self, Read}, @@ -11,6 +12,7 @@ use bip39::{Language, Mnemonic}; use ctr::{cipher::StreamCipher, Ctr128BE}; use hmac::{Hmac, Mac}; use pbkdf2::pbkdf2; +use rand::RngCore; use scrypt::{scrypt, Params}; use serde_json::json; use sha2::{Digest, Sha256, Sha512}; @@ -22,13 +24,12 @@ use crate::{ private_key::{PrivateKey, PRIVATE_KEY_LENGTH}, public_key::PublicKey, }, - data::{ - address::Address, - keystore::{DecryptionParams, Keystore, WalletError}, - transaction::Transaction, - }, + data::{address::Address, keystore::*, transaction::Transaction}, + utils::base64_decode, }; +use uuid::Uuid; + const EGLD_COIN_TYPE: u32 = 508; const HARDENED: u32 = 0x80000000; const CIPHER_ALGORITHM_AES_128_CTR: &str = "aes-128-ctr"; @@ -79,6 +80,7 @@ impl Wallet { let mut digest = HmacSha512::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(b"ed25519 seed").expect("HMAC can take key of any size"); digest.update(&seed); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); let mut key = intermediary[..serialized_key_len].to_vec(); @@ -99,6 +101,7 @@ impl Wallet { digest = HmacSha512::new_from_slice(&chain_code).expect("HMAC can take key of any size"); + HmacSha512::new_from_slice(&chain_code).expect("HMAC can take key of any size"); digest.update(&buff); let intermediary: Vec = digest.finalize().into_bytes().into_iter().collect(); key = intermediary[..serialized_key_len].to_vec(); @@ -108,9 +111,20 @@ impl Wallet { PrivateKey::from_bytes(key.as_slice()).unwrap() } + pub fn get_wallet_keys_mnemonic(mnemonic_str: String) -> (String, String) { + let mnemonic = Mnemonic::parse(mnemonic_str.replace('\n', "")).unwrap(); + let private_key = Self::get_private_key_from_mnemonic(mnemonic, 0u32, 0u32); + let public_key = PublicKey::from(&private_key); + + let public_key_str: &str = &public_key.to_string(); + let private_key_str: &str = &private_key.to_string(); + + (private_key_str.to_string(), public_key_str.to_string()) + } + pub fn from_private_key(priv_key: &str) -> Result { - let pri_key = PrivateKey::from_hex_str(priv_key)?; - Ok(Self { priv_key: pri_key }) + let priv_key = PrivateKey::from_hex_str(priv_key)?; + Ok(Self { priv_key }) } pub fn from_pem_file(file_path: &str) -> Result { @@ -126,25 +140,45 @@ impl Wallet { Ok(Self { priv_key: pri_key }) } + pub fn get_pem_decoded_content(file: &str) -> Vec { + let pem_content = fs::read_to_string(file).unwrap(); + let lines: Vec<&str> = pem_content.split('\n').collect(); + let pem_encoded_keys = format!("{}{}{}", lines[1], lines[2], lines[3]); + base64_decode(pem_encoded_keys) + } + + pub fn get_wallet_keys_pem(file: &str) -> (String, String) { + let pem_decoded_keys = Self::get_pem_decoded_content(file); + let (private_key, public_key) = pem_decoded_keys.split_at(pem_decoded_keys.len() / 2); + let private_key_str = String::from_utf8(private_key.to_vec()).unwrap(); + let public_key_str = String::from_utf8(public_key.to_vec()).unwrap(); + + (private_key_str, public_key_str) + } + pub fn from_keystore_secret(file_path: &str) -> Result { let decyption_params = Self::validate_keystore_password(file_path, Self::get_keystore_password()) .unwrap_or_else(|e| { panic!("Error: {:?}", e); }); - let priv_key = - PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + let priv_key = PrivateKey::from_hex_str( + hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), + )?; Ok(Self { priv_key }) } - pub fn get_private_key_from_keystore_secret(file_path: &str) -> Result { - let decyption_params = - Self::validate_keystore_password(file_path, Self::get_keystore_password()) - .unwrap_or_else(|e| { - panic!("Error: {:?}", e); - }); - let priv_key = - PrivateKey::from_hex_str(Self::decrypt_secret_key(decyption_params).as_str())?; + pub fn get_private_key_from_keystore_secret( + file_path: &str, + password: &str, + ) -> Result { + let decyption_params = Self::validate_keystore_password(file_path, password.to_string()) + .unwrap_or_else(|e| { + panic!("Error: {:?}", e); + }); + let priv_key = PrivateKey::from_hex_str( + hex::encode(Self::decrypt_secret_key(decyption_params)).as_str(), + )?; Ok(priv_key) } @@ -169,7 +203,7 @@ impl Wallet { self.priv_key.sign(tx_bytes) } - fn get_keystore_password() -> String { + pub fn get_keystore_password() -> String { println!( "Insert password. Press 'Ctrl-D' (Linux / MacOS) or 'Ctrl-Z' (Windows) when done." ); @@ -222,7 +256,7 @@ impl Wallet { Ok(DecryptionParams { derived_key_first_half, iv, - ciphertext, + data: ciphertext, }) } else { println!("Password is incorrect"); @@ -230,14 +264,73 @@ impl Wallet { } } - pub fn decrypt_secret_key(decryption_params: DecryptionParams) -> String { + pub fn decrypt_secret_key(decryption_params: DecryptionParams) -> Vec { let mut cipher = Ctr128BE::::new( decryption_params.derived_key_first_half.as_slice().into(), decryption_params.iv.as_slice().into(), ); - let mut decrypted = decryption_params.ciphertext.to_vec(); + let mut decrypted = decryption_params.data.to_vec(); cipher.apply_keystream(&mut decrypted); - hex::encode(decrypted).to_string() + decrypted + } + + pub fn encrypt_keystore( + data: &[u8], + address: &Address, + public_key: &str, + password: &str, + ) -> String { + let params = Params::new((KDF_N as f64).log2() as u8, KDF_R, KDF_P, KDF_DKLEN).unwrap(); + let mut rand_salt: [u8; 32] = [0u8; 32]; + rand::thread_rng().fill_bytes(&mut rand_salt); + let salt_hex = hex::encode(rand_salt); + + let mut rand_iv: [u8; 16] = [0u8; 16]; + rand::thread_rng().fill_bytes(&mut rand_iv); + let iv_hex = hex::encode(rand_iv); + + let mut derived_key = vec![0u8; 32]; + scrypt(password.as_bytes(), &rand_salt, ¶ms, &mut derived_key).unwrap(); + + let derived_key_first_half = derived_key[0..16].to_vec(); + let derived_key_second_half = derived_key[16..32].to_vec(); + + let decryption_params = DecryptionParams { + derived_key_first_half, + iv: rand_iv.to_vec(), + data: data.to_vec(), + }; + + let ciphertext = Self::decrypt_secret_key(decryption_params); + + let mut h = HmacSha256::new_from_slice(&derived_key_second_half).unwrap(); + h.update(&ciphertext); + let mac = h.finalize().into_bytes(); + let keystore = Keystore { + crypto: Crypto { + cipher: CIPHER_ALGORITHM_AES_128_CTR.to_string(), + cipherparams: CryptoParams { iv: iv_hex }, + ciphertext: hex::encode(&ciphertext), + kdf: KDF_SCRYPT.to_string(), + kdfparams: KdfParams { + salt: salt_hex, + n: KDF_N, + r: KDF_R, + p: KDF_P, + dklen: KDF_DKLEN as u32, + }, + mac: hex::encode(mac), + }, + id: Uuid::new_v4().to_string(), + version: KEYSTORE_VERSION, + kind: "secretKey".to_string(), + address: public_key.to_string(), + bech32: address.to_string(), + }; + + let mut keystore_json: String = serde_json::to_string_pretty(&keystore).unwrap(); + keystore_json.push('\n'); + keystore_json } } From 59ef56038c4f7975091df2f363c9c91dad34cb9b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Wed, 21 Aug 2024 22:49:00 +0200 Subject: [PATCH 19/52] whitebox migration for price aggregator, transfer role, gov module --- .../tests/price_aggregator_whitebox_test.rs | 562 +++++++------- .../tests/transfer_role_whitebox_test.rs | 230 +++--- .../tests/gov_module_whitebox_test.rs | 723 +++++++++--------- 3 files changed, 756 insertions(+), 759 deletions(-) diff --git a/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs b/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs index 180301b610..46ce6f52c3 100644 --- a/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs +++ b/contracts/core/price-aggregator/tests/price_aggregator_whitebox_test.rs @@ -4,7 +4,7 @@ use multiversx_price_aggregator_sc::{ }; use multiversx_sc_modules::{ pause::EndpointWrappers as PauseEndpointWrappers, - staking::EndpointWrappers as StakingEndpointWrappers, + staking::{EndpointWrappers as StakingEndpointWrappers, StakingModule}, }; use multiversx_sc_scenario::imports::*; @@ -17,9 +17,10 @@ pub const STAKE_AMOUNT: u64 = 20; pub const SUBMISSION_COUNT: usize = 3; pub const USD_TICKER: &[u8] = b"USDC"; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const PRICE_AGGREGATOR_ADDRESS_EXPR: &str = "sc:price-aggregator"; -const PRICE_AGGREGATOR_PATH_EXPR: &str = "mxsc:output/multiversx-price-aggregator-sc.mxsc.json"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const PRICE_AGGREGATOR_ADDRESS: TestSCAddress = TestSCAddress::new("price-aggregator"); +const PRICE_AGGREGATOR_PATH_EXPR: MxscPath = + MxscPath::new("mxsc:output/multiversx-price-aggregator-sc.mxsc.json"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -35,31 +36,27 @@ fn world() -> ScenarioWorld { #[test] fn test_price_aggregator_submit() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); // configure the number of decimals - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.set_pair_decimals( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), DECIMALS, ) - }, - ); + }); // try submit while paused - world.whitebox_call_check( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[0]) - .expect(TxExpect::user_error("str:Contract is paused")), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .returns(ExpectError(4u64, "Contract is paused")) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -67,22 +64,24 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) - }, - |r| r.assert_user_error("Contract is paused"), - ); + }); // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); // submit first timestamp too old - world.whitebox_call_check( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]).no_expect(), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .returns(ExpectError(4u64, "First submission too old")) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -90,17 +89,14 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) - }, - |r| { - r.assert_user_error("First submission too old"); - }, - ); + }); // submit ok - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -108,49 +104,50 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) - }, - ); + }); let current_timestamp = 100; - world.whitebox_query(&price_aggregator_whitebox, |sc| { - let token_pair = TokenPair { - from: managed_buffer!(EGLD_TICKER), - to: managed_buffer!(USD_TICKER), - }; - assert_eq!( - sc.first_submission_timestamp(&token_pair).get(), - current_timestamp - ); - assert_eq!( - sc.last_submission_timestamp(&token_pair).get(), - current_timestamp - ); - - let submissions = sc.submissions().get(&token_pair).unwrap(); - assert_eq!(submissions.len(), 1); - assert_eq!( - submissions - .get(&managed_address!(&oracles[0].to_address())) - .unwrap(), - managed_biguint!(100) - ); - - assert_eq!( - sc.oracle_status() - .get(&managed_address!(&oracles[0].to_address())) - .unwrap(), - OracleStatus { - total_submissions: 1, - accepted_submissions: 1 - } - ); - }); + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let token_pair = TokenPair { + from: managed_buffer!(EGLD_TICKER), + to: managed_buffer!(USD_TICKER), + }; + assert_eq!( + sc.first_submission_timestamp(&token_pair).get(), + current_timestamp + ); + assert_eq!( + sc.last_submission_timestamp(&token_pair).get(), + current_timestamp + ); + + let submissions = sc.submissions().get(&token_pair).unwrap(); + assert_eq!(submissions.len(), 1); + assert_eq!( + submissions.get(&ManagedAddress::from(&oracles[0])).unwrap(), + managed_biguint!(100) + ); + + assert_eq!( + sc.oracle_status() + .get(&ManagedAddress::from(&oracles[0])) + .unwrap(), + OracleStatus { + total_submissions: 1, + accepted_submissions: 1 + } + ); + }, + ); // first oracle submit again - submission not accepted - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -158,55 +155,56 @@ fn test_price_aggregator_submit() { managed_biguint!(100), DECIMALS, ) + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + assert_eq!( + sc.oracle_status() + .get(&ManagedAddress::from(&oracles[0])) + .unwrap(), + OracleStatus { + total_submissions: 2, + accepted_submissions: 1 + } + ); }, ); - - world.whitebox_query(&price_aggregator_whitebox, |sc| { - assert_eq!( - sc.oracle_status() - .get(&managed_address!(&oracles[0].to_address())) - .unwrap(), - OracleStatus { - total_submissions: 2, - accepted_submissions: 1 - } - ); - }); } #[test] fn test_price_aggregator_submit_round_ok() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); // configure the number of decimals - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.set_pair_decimals( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), DECIMALS, ) - }, - ); + }); // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); // submit first - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -214,17 +212,17 @@ fn test_price_aggregator_submit_round_ok() { managed_biguint!(10_000), DECIMALS, ) - }, - ); + }); let current_timestamp = 110; - world.set_state_step(SetStateStep::new().block_timestamp(current_timestamp)); + world.current_block().block_timestamp(current_timestamp); // submit second - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[1]), - |sc| { + world + .tx() + .from(&oracles[1]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -232,14 +230,14 @@ fn test_price_aggregator_submit_round_ok() { managed_biguint!(11_000), DECIMALS, ) - }, - ); + }); // submit third - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[2]), - |sc| { + world + .tx() + .from(&oracles[2]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -247,72 +245,73 @@ fn test_price_aggregator_submit_round_ok() { managed_biguint!(12_000), DECIMALS, ) + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let result = + sc.latest_price_feed(managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER)); + + let (round_id, from, to, timestamp, price, decimals) = result.into_tuple(); + assert_eq!(round_id, 1); + assert_eq!(from, managed_buffer!(EGLD_TICKER)); + assert_eq!(to, managed_buffer!(USD_TICKER)); + assert_eq!(timestamp, current_timestamp); + assert_eq!(price, managed_biguint!(11_000)); + assert_eq!(decimals, DECIMALS); + + // submissions are deleted after round is created + let token_pair = TokenPair { from, to }; + let submissions = sc.submissions().get(&token_pair).unwrap(); + assert_eq!(submissions.len(), 0); + + let rounds = sc.rounds().get(&token_pair).unwrap(); + assert_eq!(rounds.len(), 1); + assert_eq!( + rounds.get(1), + TimestampedPrice { + timestamp, + price, + decimals + } + ); }, ); - - world.whitebox_query(&price_aggregator_whitebox, |sc| { - let result = - sc.latest_price_feed(managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER)); - - let (round_id, from, to, timestamp, price, decimals) = result.into_tuple(); - assert_eq!(round_id, 1); - assert_eq!(from, managed_buffer!(EGLD_TICKER)); - assert_eq!(to, managed_buffer!(USD_TICKER)); - assert_eq!(timestamp, current_timestamp); - assert_eq!(price, managed_biguint!(11_000)); - assert_eq!(decimals, DECIMALS); - - // submissions are deleted after round is created - let token_pair = TokenPair { from, to }; - let submissions = sc.submissions().get(&token_pair).unwrap(); - assert_eq!(submissions.len(), 0); - - let rounds = sc.rounds().get(&token_pair).unwrap(); - assert_eq!(rounds.len(), 1); - assert_eq!( - rounds.get(1), - TimestampedPrice { - timestamp, - price, - decimals - } - ); - }); } #[test] fn test_price_aggregator_discarded_round() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); // configure the number of decimals - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.set_pair_decimals( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), DECIMALS, ) - }, - ); + }); // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); // submit first - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[0]), - |sc| { + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -320,17 +319,17 @@ fn test_price_aggregator_discarded_round() { managed_biguint!(10_000), DECIMALS, ) - }, - ); + }); let current_timestamp = 100 + MAX_ROUND_DURATION_SECONDS + 1; - world.set_state_step(SetStateStep::new().block_timestamp(current_timestamp)); + world.current_block().block_timestamp(current_timestamp); // submit second - this will discard the previous submission - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[1]), - |sc| { + world + .tx() + .from(&oracles[1]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -338,77 +337,100 @@ fn test_price_aggregator_discarded_round() { managed_biguint!(11_000), DECIMALS, ) + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let token_pair = TokenPair { + from: managed_buffer!(EGLD_TICKER), + to: managed_buffer!(USD_TICKER), + }; + let submissions = sc.submissions().get(&token_pair).unwrap(); + assert_eq!(submissions.len(), 1); + assert_eq!( + submissions.get(&managed_address!(&oracles[1])).unwrap(), + managed_biguint!(11_000) + ); }, ); - - world.whitebox_query(&price_aggregator_whitebox, |sc| { - let token_pair = TokenPair { - from: managed_buffer!(EGLD_TICKER), - to: managed_buffer!(USD_TICKER), - }; - let submissions = sc.submissions().get(&token_pair).unwrap(); - assert_eq!(submissions.len(), 1); - assert_eq!( - submissions - .get(&managed_address!(&oracles[1].to_address())) - .unwrap(), - managed_biguint!(11_000) - ); - }); } #[test] fn test_price_aggregator_slashing() { let (mut world, oracles) = setup(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); - // unpause - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| sc.call_unpause_endpoint(), - ); - - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[0]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_vote_slash_member(), - ); - - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[2]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_vote_slash_member(), - ); + // configure the number of decimals + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.set_pair_decimals( + managed_buffer!(EGLD_TICKER), + managed_buffer!(USD_TICKER), + DECIMALS, + ) + }); - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[3]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_vote_slash_member(), + // unpause + world + .tx() + .from(OWNER_ADDRESS) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_unpause_endpoint(); + }); + + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.vote_slash_member(ManagedAddress::from(&oracles[1])); + }); + + world + .tx() + .from(&oracles[2]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.vote_slash_member(ManagedAddress::from(&oracles[1])) + }); + + world + .tx() + .from(&oracles[3]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.vote_slash_member(ManagedAddress::from(&oracles[1])); + }); + + world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { + let list = sc.slashing_proposal_voters(&ManagedAddress::from(&oracles[1])); + assert!(list.contains(&ManagedAddress::from(&oracles[0]))); + assert!(list.contains(&ManagedAddress::from(&oracles[2]))); + assert!(list.contains(&ManagedAddress::from(&oracles[3]))); + }, ); - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(&oracles[0]) - .argument(BytesValue::from(oracles[1].to_address().as_bytes())), - |sc| sc.call_slash_member(), - ); + world + .tx() + .from(&oracles[0]) + .to(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.slash_member(ManagedAddress::from(&oracles[1])); + }); // oracle 1 try submit after slashing - world.whitebox_call_check( - &price_aggregator_whitebox, - ScCallStep::new().from(&oracles[1]).no_expect(), - |sc| { + world + .tx() + .from(&oracles[1]) + .to(PRICE_AGGREGATOR_ADDRESS) + .returns(ExpectError(4u64, "only oracles allowed")) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { sc.submit( managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER), @@ -416,49 +438,37 @@ fn test_price_aggregator_slashing() { managed_biguint!(10_000), DECIMALS, ) - }, - |r| { - r.assert_user_error("only oracles allowed"); - }, - ); + }); } -fn setup() -> (ScenarioWorld, Vec) { +fn setup() -> (ScenarioWorld, Vec
) { // setup let mut world = world(); - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS_EXPR, - multiversx_price_aggregator_sc::contract_obj, - ); - let price_aggregator_code = world.code_expression(PRICE_AGGREGATOR_PATH_EXPR); - let mut set_state_step = SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(OWNER_ADDRESS_EXPR, 1, PRICE_AGGREGATOR_ADDRESS_EXPR) - .block_timestamp(100); + world.account(OWNER_ADDRESS).nonce(1); + world.current_block().block_timestamp(100); let mut oracles = Vec::new(); for i in 1..=NR_ORACLES { - let oracle_address_expr = format!("address:oracle{i}"); - let oracle_address = AddressValue::from(oracle_address_expr.as_str()); - - set_state_step = set_state_step.put_account( - oracle_address_expr.as_str(), - Account::new().nonce(1).balance(STAKE_AMOUNT), - ); - oracles.push(oracle_address); + let oracle_address_expr = format!("oracle{i}"); + let oracle_address = TestAddress::new(&oracle_address_expr); + + world.account(oracle_address).nonce(1).balance(STAKE_AMOUNT); + + oracles.push(oracle_address.to_address()); } // init price aggregator - world.set_state_step(set_state_step).whitebox_deploy( - &price_aggregator_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(price_aggregator_code), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(PRICE_AGGREGATOR_PATH_EXPR) + .new_address(PRICE_AGGREGATOR_ADDRESS) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { let mut oracle_args = MultiValueEncoded::new(); for oracle_address in &oracles { - oracle_args.push(managed_address!(&oracle_address.to_address())); + oracle_args.push(ManagedAddress::from(oracle_address)); } sc.init( @@ -469,17 +479,17 @@ fn setup() -> (ScenarioWorld, Vec) { SUBMISSION_COUNT, oracle_args, ) - }, - ); + }); for oracle_address in &oracles { - world.whitebox_call( - &price_aggregator_whitebox, - ScCallStep::new() - .from(oracle_address) - .egld_value(STAKE_AMOUNT), - |sc| sc.call_stake(), - ); + world + .tx() + .from(oracle_address) + .to(PRICE_AGGREGATOR_ADDRESS) + .egld(STAKE_AMOUNT) + .whitebox(multiversx_price_aggregator_sc::contract_obj, |sc| { + sc.call_stake(); + }); } (world, oracles) diff --git a/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs b/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs index adf9582982..130c2b237c 100644 --- a/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs +++ b/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs @@ -1,15 +1,17 @@ use multiversx_sc_modules::transfer_role_proxy::TransferRoleProxyModule; use multiversx_sc_scenario::imports::*; use transfer_role_features::TransferRoleFeatures; +use vault::Vault; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const USER_ADDRESS_EXPR: &str = "address:user"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const USER_ADDRESS: TestAddress = TestAddress::new("user"); -const TRANSFER_ROLE_FEATURES_ADDRESS_EXPR: &str = "sc:transfer-role-features"; -const TRANSFER_ROLE_FEATURES_PATH_EXPR: &str = "mxsc:output/transfer-role-features.mxsc.json"; +const TRANSFER_ROLE_FEATURES_ADDRESS: TestSCAddress = TestSCAddress::new("transfer-role-features"); +const TRANSFER_ROLE_FEATURES_PATH_EXPR: MxscPath = + MxscPath::new("mxsc:output/transfer-role-features.mxsc.json"); -const TRANSFER_TOKEN_ID_EXPR: &str = "str:TRANSFER-123456"; -const TRANSFER_TOKEN_ID: &[u8] = b"TRANSFER-123456"; +const TRANSFER_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("TRANSFER-123456"); +const TRANSFER_TOKEN_ID_EXPR: &[u8] = b"TRANSFER-123456"; const ACCEPT_FUNDS_FUNC_NAME: &[u8] = b"accept_funds"; const REJECT_FUNDS_FUNC_NAME: &[u8] = b"reject_funds"; @@ -27,175 +29,161 @@ fn world() -> ScenarioWorld { fn test_transfer_role() { let mut world = world(); - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(OWNER_ADDRESS_EXPR, 1, TRANSFER_ROLE_FEATURES_ADDRESS_EXPR) - .put_account( - USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(TRANSFER_TOKEN_ID_EXPR, 1_000u64), - ), - ); + world.account(OWNER_ADDRESS).nonce(1); + world + .account(USER_ADDRESS) + .nonce(1) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(1_000u64)); // vault - let vault_code = world.code_expression(VAULT_PATH_EXPR); - - const VAULT_ADDRESS_EXPR: &str = "sc:vault"; - const VAULT_PATH_EXPR: &str = "mxsc:../vault/output/vault.mxsc.json"; + const VAULT_ADDRESS: TestSCAddress = TestSCAddress::new("vault"); + const VAULT_PATH_EXPR: MxscPath = MxscPath::new("mxsc:../vault/output/vault.mxsc.json"); world.register_contract(VAULT_PATH_EXPR, vault::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(VAULT_ADDRESS_EXPR, Account::new().nonce(1).code(vault_code)), - ); - - let transfer_role_features_whitebox = WhiteboxContract::new( - TRANSFER_ROLE_FEATURES_ADDRESS_EXPR, - transfer_role_features::contract_obj, - ); - let transfer_role_features_code = world.code_expression(TRANSFER_ROLE_FEATURES_PATH_EXPR); + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .new_address(VAULT_ADDRESS) + .code(VAULT_PATH_EXPR) + .whitebox(vault::contract_obj, |sc| { + let _ = sc.init(OptionalValue::None); + }); // init - world.whitebox_deploy( - &transfer_role_features_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(transfer_role_features_code), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .new_address(TRANSFER_ROLE_FEATURES_ADDRESS) + .code(TRANSFER_ROLE_FEATURES_PATH_EXPR) + .whitebox(transfer_role_features::contract_obj, |sc| { let mut whitelist = MultiValueEncoded::new(); - whitelist.push(managed_address!(&address_expr_to_address( - OWNER_ADDRESS_EXPR - ))); - whitelist.push(managed_address!(&address_expr_to_address( - VAULT_ADDRESS_EXPR - ))); + whitelist.push(OWNER_ADDRESS.to_managed_address()); + whitelist.push(VAULT_ADDRESS.to_managed_address()); sc.init(whitelist); - }, - ); + }); // transfer to user - ok - world.whitebox_call( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100"), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_user( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - managed_address!(&address_expr_to_address(OWNER_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), + OWNER_ADDRESS.to_managed_address(), &payments, managed_buffer!(b"enjoy"), ); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "900"), - )); - world.check_state_step(CheckStateStep::new().put_account( - OWNER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "100"), - )); + world + .check_account(USER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(900u64)); + world + .check_account(OWNER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(100u64)); // transfer to user - err, not whitelisted - world.whitebox_call_check( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100") - .no_expect(), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .returns(ExpectError(4u64, "Destination address not whitelisted")) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_user( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), managed_address!(&Address::zero()), &payments, managed_buffer!(b"enjoy"), ); - }, - |r| { - r.assert_user_error("Destination address not whitelisted"); - }, - ); + }); // transfer to sc - ok - world.whitebox_call( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100"), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_contract_raw( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - managed_address!(&address_expr_to_address(VAULT_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), + VAULT_ADDRESS.to_managed_address(), &payments, managed_buffer!(ACCEPT_FUNDS_FUNC_NAME), ManagedArgBuffer::new(), None, ); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "800"), - )); - world.check_state_step(CheckStateStep::new().put_account( - VAULT_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "100"), - )); + world + .check_account(USER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(800u64)); + world + .check_account(VAULT_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(100u64)); // transfer to sc - reject - world.whitebox_call( - &transfer_role_features_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(TRANSFER_TOKEN_ID, 0, "100"), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(TRANSFER_ROLE_FEATURES_ADDRESS) + .single_esdt( + &TokenIdentifier::from(TRANSFER_TOKEN_ID), + 0, + &BigUint::from(100u64), + ) + .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( - managed_token_id!(TRANSFER_TOKEN_ID), + managed_token_id!(TRANSFER_TOKEN_ID_EXPR), 0, managed_biguint!(100), )); sc.transfer_to_contract_raw( - managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - managed_address!(&address_expr_to_address(VAULT_ADDRESS_EXPR)), + USER_ADDRESS.to_managed_address(), + VAULT_ADDRESS.to_managed_address(), &payments, managed_buffer!(REJECT_FUNDS_FUNC_NAME), ManagedArgBuffer::new(), None, ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "800"), - )); - world.check_state_step(CheckStateStep::new().put_account( - VAULT_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(TRANSFER_TOKEN_ID_EXPR, "100"), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + }); + + world + .check_account(USER_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(800u64)); + world + .check_account(VAULT_ADDRESS) + .esdt_balance(TRANSFER_TOKEN_ID, BigUint::from(100u64)); } diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 72b15aac66..288d3042f5 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -4,7 +4,7 @@ use multiversx_sc_modules::governance::{ }; use multiversx_sc_scenario::imports::*; -const GOV_TOKEN_ID_EXPR: &str = "str:GOV-123456"; +const GOV_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("GOV-123456"); const GOV_TOKEN_ID: &[u8] = b"GOV-123456"; const QUORUM: u64 = 1_500; const MIN_BALANCE_PROPOSAL: u64 = 500; @@ -15,13 +15,13 @@ const LOCKING_PERIOD_BLOCKS: u64 = 30; const INITIAL_GOV_TOKEN_BALANCE: u64 = 1_000; const GAS_LIMIT: u64 = 1_000_000; -const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; -const USE_MODULE_PATH_EXPR: &str = "mxsc:output/use-module.mxsc.json"; +const USE_MODULE_ADDRESS: TestSCAddress = TestSCAddress::new("use-module"); +const USE_MODULE_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/use-module.mxsc.json"); -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const FIRST_USER_ADDRESS_EXPR: &str = "address:first-user"; -const SECOND_USER_ADDRESS_EXPR: &str = "address:second-user"; -const THIRD_USER_ADDRESS_EXPR: &str = "address:third-user"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const FIRST_USER_ADDRESS: TestAddress = TestAddress::new("first-user"); +const SECOND_USER_ADDRESS: TestAddress = TestAddress::new("second-user"); +const THIRD_USER_ADDRESS: TestAddress = TestAddress::new("third-user"); pub struct Payment { pub token: Vec, @@ -39,58 +39,45 @@ fn world() -> ScenarioWorld { fn setup() -> ScenarioWorld { let mut world = world(); - world.set_state_step( - SetStateStep::new() - .put_account( - OWNER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), - ) - .new_address(OWNER_ADDRESS_EXPR, 1, USE_MODULE_ADDRESS_EXPR) - .put_account( - FIRST_USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), - ) - .put_account( - SECOND_USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), - ) - .put_account( - THIRD_USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE), - ), - ); + world + .account(OWNER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + world + .account(FIRST_USER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + world + .account(SECOND_USER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + world + .account(THIRD_USER_ADDRESS) + .nonce(1) + .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); // init - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); - - world.whitebox_deploy( - &use_module_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(use_module_code), - |sc| { + let new_address = world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(USE_MODULE_PATH_EXPR) + .new_address(USE_MODULE_ADDRESS) + .returns(ReturnsNewBech32Address) + .whitebox(use_module::contract_obj, |sc| { sc.init_governance_module( - managed_token_id!(GOV_TOKEN_ID), - managed_biguint!(QUORUM), - managed_biguint!(MIN_BALANCE_PROPOSAL), + TokenIdentifier::from(GOV_TOKEN_ID_EXPR), + BigUint::from(QUORUM), + BigUint::from(MIN_BALANCE_PROPOSAL), VOTING_DELAY_BLOCKS, VOTING_PERIOD_BLOCKS, LOCKING_PERIOD_BLOCKS, ); - }, - ); + }); - world.set_state_step(SetStateStep::new().block_nonce(10)); + assert_eq!(new_address.to_address(), USE_MODULE_ADDRESS.to_address()); + + world.current_block().block_nonce(10); world } @@ -103,17 +90,18 @@ pub fn propose( endpoint_name: &[u8], args: Vec>, ) -> usize { - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let mut proposal_id = 0; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(proposer) - .esdt_transfer(GOV_TOKEN_ID, 0, gov_token_amount), - |sc| { + world + .tx() + .from(proposer) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID_EXPR), + 0, + &BigUint::from(gov_token_amount), + ) + .whitebox(use_module::contract_obj, |sc| { let mut args_managed = ManagedVec::new(); for arg in args { args_managed.push(managed_buffer!(&arg)); @@ -131,8 +119,7 @@ pub fn propose( ); proposal_id = sc.propose(managed_buffer!(b"change quorum"), actions); - }, - ); + }); proposal_id } @@ -145,16 +132,14 @@ fn test_init() { #[test] fn test_change_gov_config() { let mut world = setup(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); let mut current_block_nonce = 10; let proposal_id = propose( &mut world, - &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -162,209 +147,212 @@ fn test_change_gov_config() { assert_eq!(proposal_id, 1); // vote too early - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new() - .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "999") - .no_expect(), - |sc| { + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(999u64), + ) + .returns(ExpectError(4u64, "Proposal is not active")) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - |r| { - r.assert_user_error("Proposal is not active"); - }, - ); + }); current_block_nonce += VOTING_DELAY_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "999"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(999u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - ); + }); // try execute before queue - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only execute queued proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.execute(proposal_id); - }, - |r| { - r.assert_user_error("Can only execute queued proposals"); - }, - ); + }); // try queue before voting ends - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); current_block_nonce += VOTING_PERIOD_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); + world.current_block().block_nonce(current_block_nonce); // try queue not enough votes - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); // user 1 vote again current_block_nonce = 20; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "200"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - ); + }); // owner downvote - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(OWNER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "200"), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); - }, - ); + }); // try queue too many downvotes current_block_nonce = 45; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); // user 1 vote again current_block_nonce = 20; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new() - .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "200") - .no_expect(), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .returns(ExpectError(4u64, "Already voted for this proposal")) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - |r| { - r.assert_user_error("Already voted for this proposal"); - }, - ); + }); // user 3 vote again - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(THIRD_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "200"), - |sc| { + world + .tx() + .from(THIRD_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - ); + }); // queue ok current_block_nonce = 45; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - ); + }); // try execute too early - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { - sc.execute(proposal_id); - }, - |r| { - r.assert_user_error("Proposal is in timelock status. Try again later"); - }, - ); + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError( + 4u64, + "Proposal is in timelock status. Try again later", + )) + .whitebox(use_module::contract_obj, |sc| sc.execute(proposal_id)); // execute ok current_block_nonce += LOCKING_PERIOD_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { - sc.execute(proposal_id); - }, - ); + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| sc.execute(proposal_id)); // after execution, quorum changed from 1_500 to the proposed 1_000 - world.whitebox_query(&use_module_whitebox, |sc| { - assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); - assert!(sc.proposals().item_is_empty(1)); - }); - - world.check_state_step(CheckStateStep::new().put_account( - FIRST_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "300"), - )); - world.check_state_step(CheckStateStep::new().put_account( - SECOND_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "1"), - )); - world.check_state_step(CheckStateStep::new().put_account( - THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), - )); - world.check_state_step(CheckStateStep::new().put_account( - OWNER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), - )); + world + .query() + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); + assert!(sc.proposals().item_is_empty(1)); + }); + + world + .check_account(FIRST_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(300u64)); + world + .check_account(SECOND_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(1u64)); + world + .check_account(THIRD_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + world + .check_account(OWNER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); } #[test] fn test_down_veto_gov_config() { let mut world = setup(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); let mut current_block_nonce = 10; let proposal_id = propose( &mut world, - &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -372,81 +360,87 @@ fn test_down_veto_gov_config() { assert_eq!(proposal_id, 1); current_block_nonce += VOTING_DELAY_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "300"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(300u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - ); + }); current_block_nonce = 20; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "200"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - ); + }); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(THIRD_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "200"), - |sc| { - sc.vote(proposal_id, VoteType::DownVetoVote); - }, - ); + world + .tx() + .from(THIRD_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(200u64), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.vote(proposal_id, VoteType::DownVetoVote) + }); // Vote didn't succeed; current_block_nonce = 45; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world.current_block().block_epoch(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Can only queue succeeded proposals")) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - |r| { - r.assert_user_error("Can only queue succeeded proposals"); - }, - ); + }); + + world + .check_account(FIRST_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(200u64)); - world.check_state_step(CheckStateStep::new().put_account( - FIRST_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "200"), - )); - world.check_state_step(CheckStateStep::new().put_account( - SECOND_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), - )); - world.check_state_step(CheckStateStep::new().put_account( - THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "800"), - )); + world + .check_account(SECOND_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + + world + .check_account(THIRD_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); } #[test] fn test_abstain_vote_gov_config() { let mut world = setup(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); let mut current_block_nonce = 10; let proposal_id = propose( &mut world, - &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -454,95 +448,105 @@ fn test_abstain_vote_gov_config() { assert_eq!(proposal_id, 1); current_block_nonce += VOTING_DELAY_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(FIRST_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "500"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(500u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); - }, - ); + }); current_block_nonce = 20; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "400"), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(400u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); - }, - ); + }); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(THIRD_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "600"), - |sc| { + world + .tx() + .from(THIRD_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(600u64), + ) + .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::AbstainVote); - }, - ); + }); // Vote didn't succeed; current_block_nonce = 45; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { sc.queue(proposal_id); - }, - ); + }); // execute ok current_block_nonce += LOCKING_PERIOD_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(FIRST_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(FIRST_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { sc.execute(proposal_id); - }, - ); + }); // after execution, quorum changed from 1_500 to the proposed 1_000 - world.whitebox_query(&use_module_whitebox, |sc| { - assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); - assert!(sc.proposals().item_is_empty(1)); - }); - - world.check_state_step(CheckStateStep::new().put_account( - FIRST_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "0"), - )); - world.check_state_step(CheckStateStep::new().put_account( - SECOND_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "600"), - )); - world.check_state_step(CheckStateStep::new().put_account( - THIRD_USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(GOV_TOKEN_ID_EXPR, "400"), - )); + world + .query() + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| { + assert_eq!(sc.quorum().get(), managed_biguint!(1_000)); + assert!(sc.proposals().item_is_empty(1)); + }); + + world + .check_account(FIRST_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::zero()); + world + .check_account(SECOND_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(600u64)); + world + .check_account(THIRD_USER_ADDRESS) + .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(400u64)); } #[test] fn test_gov_cancel_defeated_proposal() { let mut world = setup(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); let mut current_block_nonce = 10; let proposal_id = propose( &mut world, - &address_expr_to_address(FIRST_USER_ADDRESS_EXPR), + &FIRST_USER_ADDRESS.to_address(), 500, - &address_expr_to_address(USE_MODULE_ADDRESS_EXPR), + &USE_MODULE_ADDRESS.to_address(), b"changeQuorum", vec![1_000u64.to_be_bytes().to_vec()], ); @@ -550,42 +554,37 @@ fn test_gov_cancel_defeated_proposal() { assert_eq!(proposal_id, 1); current_block_nonce += VOTING_DELAY_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(SECOND_USER_ADDRESS_EXPR) - .esdt_transfer(GOV_TOKEN_ID, 0, "999"), - |sc| { - sc.vote(proposal_id, VoteType::DownVote); - }, - ); + world.current_block().block_nonce(current_block_nonce); + + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .single_esdt( + &TokenIdentifier::from(GOV_TOKEN_ID), + 0, + &BigUint::from(999u64), + ) + .whitebox(use_module::contract_obj, |sc| { + sc.vote(proposal_id, VoteType::DownVote) + }); // try cancel too early - world.whitebox_call_check( - &use_module_whitebox, - ScCallStep::new().from(SECOND_USER_ADDRESS_EXPR).no_expect(), - |sc| { + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .returns(ExpectError(4u64, "Action may not be cancelled")) + .whitebox(use_module::contract_obj, |sc| { sc.cancel(proposal_id); - }, - |r| { - r.assert_user_error("Action may not be cancelled"); - }, - ); + }); current_block_nonce += VOTING_PERIOD_BLOCKS; - world.set_state_step(SetStateStep::new().block_nonce(current_block_nonce)); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(SECOND_USER_ADDRESS_EXPR).no_expect(), - |sc| { - sc.cancel(proposal_id); - }, - ); -} + world.current_block().block_nonce(current_block_nonce); -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world + .tx() + .from(SECOND_USER_ADDRESS) + .to(USE_MODULE_ADDRESS) + .whitebox(use_module::contract_obj, |sc| sc.cancel(proposal_id)); } From c00a93f34d44201e5a3585c10adb6f0c578c1f04 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 22 Aug 2024 11:07:37 +0300 Subject: [PATCH 20/52] fixed unittests + small refactors --- framework/meta/src/cmd/wallet.rs | 28 +-------- framework/meta/tests/wallet_test.rs | 91 ----------------------------- sdk/core/src/wallet.rs | 24 +++++++- sdk/core/tests/wallet_test.rs | 68 +++++++++++++++++++++ 4 files changed, 94 insertions(+), 117 deletions(-) delete mode 100644 framework/meta/tests/wallet_test.rs diff --git a/framework/meta/src/cmd/wallet.rs b/framework/meta/src/cmd/wallet.rs index ba8a9f6132..b3833da517 100644 --- a/framework/meta/src/cmd/wallet.rs +++ b/framework/meta/src/cmd/wallet.rs @@ -3,7 +3,7 @@ use core::str; use crate::cli::{WalletAction, WalletArgs, WalletBech32Args, WalletConvertArgs, WalletNewArgs}; use multiversx_sc::types::{self}; use multiversx_sc_snippets::sdk::{ - crypto::public_key::PublicKey, data::address::Address, utils::base64_encode, wallet::Wallet, + crypto::public_key::PublicKey, data::address::Address, wallet::Wallet, }; use multiversx_sc_snippets::{hex, imports::Bech32Address}; use std::{ @@ -90,12 +90,12 @@ fn write_resulted_pem(public_key: &str, private_key: &str, outfile: Option<&Stri let address = get_wallet_address(private_key); match outfile { Some(outfile) => { - let pem_content = generate_pem_content(&address, private_key, public_key); + let pem_content = Wallet::generate_pem_content(&address, private_key, public_key); let mut file = File::create(outfile).unwrap(); file.write_all(pem_content.as_bytes()).unwrap(); }, None => { - let pem_content = generate_pem_content(&address, private_key, public_key); + let pem_content = Wallet::generate_pem_content(&address, private_key, public_key); print!("{}", pem_content); }, } @@ -174,25 +174,3 @@ fn new(new_args: &WalletNewArgs) { None => {}, } } - -pub fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { - let concat_keys = format!("{}{}", private_key, public_key); - let concat_keys_b64 = base64_encode(concat_keys); - - // Split the base64 string into 64-character lines - let formatted_key = concat_keys_b64 - .as_bytes() - .chunks(64) - .map(|chunk| std::str::from_utf8(chunk).unwrap()) - .collect::>() - .join("\n"); - - let pem_content = format!( - "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----\n", - address.to_bech32_string().unwrap(), - formatted_key, - address.to_bech32_string().unwrap() - ); - - pem_content -} diff --git a/framework/meta/tests/wallet_test.rs b/framework/meta/tests/wallet_test.rs deleted file mode 100644 index ce1627ff64..0000000000 --- a/framework/meta/tests/wallet_test.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::fs::{self, File}; -use std::io::Write; - -use multiversx_sc_meta::cmd::wallet::generate_pem_content; -use multiversx_sc_snippets::sdk::{crypto::public_key::PublicKey, data::address::Address}; -use multiversx_sc_snippets::{hex, imports::Wallet}; - -const ALICE_PEM_PATH: &str = "../snippets/src/test_wallets/alice.pem"; -const ALICE_KEYSTORE_PATH_TEST: &str = "alice.json"; -const ALICE_PEM_PATH_TEST: &str = "alice_test.pem"; -const KEYSTORE_PASSWORD: &str = "abcd"; - -fn create_keystore_from_pem(file: &str) { - let pem_decoded_keys = Wallet::get_pem_decoded_content(file); - let (private_key_str, public_key_str) = Wallet::get_wallet_keys_pem(file); - - let address = Wallet::from_private_key(&private_key_str) - .unwrap() - .address(); - let hex_decoded_keys = hex::decode(pem_decoded_keys).unwrap(); - - let json_result = Wallet::encrypt_keystore( - hex_decoded_keys.as_slice(), - &address, - &public_key_str, - KEYSTORE_PASSWORD, - ); - - write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); -} - -fn write_to_file(content: &str, file: &str) { - let mut file = File::create(file).unwrap(); - file.write_all(content.as_bytes()).unwrap(); -} - -fn create_keystore_file_from_scratch() -> Address { - let mnemonic = Wallet::generate_mnemonic(); - let (private_key_str, public_key_str) = Wallet::get_wallet_keys_mnemonic(mnemonic.to_string()); - let wallet = Wallet::from_private_key(&private_key_str).unwrap(); - let address = wallet.address(); - - let concatenated_keys = format!("{}{}", private_key_str, public_key_str); - let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); - let json_result = Wallet::encrypt_keystore( - hex_decoded_keys.as_slice(), - &address, - &public_key_str, - KEYSTORE_PASSWORD, - ); - write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); - address -} - -#[test] -fn test_wallet_convert_pem_to_keystore() { - create_keystore_from_pem(ALICE_PEM_PATH); - let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); - assert_eq!( - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) - .unwrap() - .to_string(), - private_key_pem - ); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); -} - -#[test] -fn test_wallet_convert_keystore_to_pem() { - let address = create_keystore_file_from_scratch(); - - let private_key = - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) - .unwrap(); - let private_key_str = private_key.to_string(); - let public_key = PublicKey::from(&private_key); - let public_key_str = public_key.to_string(); - - let pem_content = generate_pem_content(&address, &private_key_str, &public_key_str); - write_to_file(&pem_content, ALICE_PEM_PATH_TEST); - - assert_eq!( - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) - .unwrap() - .to_string(), - Wallet::get_wallet_keys_pem(ALICE_PEM_PATH_TEST).0 - ); - - fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); -} diff --git a/sdk/core/src/wallet.rs b/sdk/core/src/wallet.rs index bbf2c41a2c..bf1362a314 100644 --- a/sdk/core/src/wallet.rs +++ b/sdk/core/src/wallet.rs @@ -25,7 +25,7 @@ use crate::{ public_key::PublicKey, }, data::{address::Address, keystore::*, transaction::Transaction}, - utils::base64_decode, + utils::*, }; use uuid::Uuid; @@ -333,4 +333,26 @@ impl Wallet { keystore_json.push('\n'); keystore_json } + + pub fn generate_pem_content(address: &Address, private_key: &str, public_key: &str) -> String { + let concat_keys = format!("{}{}", private_key, public_key); + let concat_keys_b64 = base64_encode(concat_keys); + + // Split the base64 string into 64-character lines + let formatted_key = concat_keys_b64 + .as_bytes() + .chunks(64) + .map(|chunk| std::str::from_utf8(chunk).unwrap()) + .collect::>() + .join("\n"); + + let pem_content = format!( + "-----BEGIN PRIVATE KEY for {}-----\n{}\n-----END PRIVATE KEY for {}-----\n", + address.to_bech32_string().unwrap(), + formatted_key, + address.to_bech32_string().unwrap() + ); + + pem_content + } } diff --git a/sdk/core/tests/wallet_test.rs b/sdk/core/tests/wallet_test.rs index d076980084..4d523d57d5 100644 --- a/sdk/core/tests/wallet_test.rs +++ b/sdk/core/tests/wallet_test.rs @@ -1,6 +1,18 @@ use bip39::Mnemonic; use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wallet::Wallet}; +use std::fs::{self, File}; +use std::io::Write; + +// use multiversx_sc_meta::cmd::wallet::generate_pem_content; +// use multiversx_sc_snippets::{hex, imports::Wallet}; + +const ALICE_PEM_PATH: &str = "tests/alice.pem"; +const ALICE_KEYSTORE_PATH_TEST: &str = "tests/alice.json"; +const ALICE_PEM_PATH_TEST: &str = "tests/alice_test.pem"; +const KEYSTORE_PASSWORD: &str = "abcd"; +const ALICE_PUBLIC_KEY: &str = "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1"; +const ALICE_PRIVATE_KEY: &str = "413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9"; #[test] fn test_private_key_from_mnemonic() { @@ -48,3 +60,59 @@ fn test_load_from_pem() { "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" ); } + +fn write_to_file(content: &str, file: &str) { + let mut file = File::create(file).unwrap(); + file.write_all(content.as_bytes()).unwrap(); +} + +fn create_keystore_file_from_scratch() -> Address { + let wallet = Wallet::from_private_key(ALICE_PRIVATE_KEY).unwrap(); + let address = wallet.address(); + + let concatenated_keys = format!("{}{}", ALICE_PRIVATE_KEY, ALICE_PUBLIC_KEY); + let hex_decoded_keys = hex::decode(concatenated_keys).unwrap(); + let json_result = Wallet::encrypt_keystore( + hex_decoded_keys.as_slice(), + &address, + ALICE_PUBLIC_KEY, + KEYSTORE_PASSWORD, + ); + write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); + address +} + +#[test] +fn test_wallet_convert_pem_to_keystore() { + let _ = create_keystore_file_from_scratch(); + let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); + assert_eq!( + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap() + .to_string(), + private_key_pem + ); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} + +#[test] +fn test_wallet_convert_keystore_to_pem() { + let address = create_keystore_file_from_scratch(); + + let private_key = + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + .unwrap(); + let private_key_str = private_key.to_string(); + let public_key = PublicKey::from(&private_key); + let public_key_str = public_key.to_string(); + + let pem_content = Wallet::generate_pem_content(&address, &private_key_str, &public_key_str); + write_to_file(&pem_content, ALICE_PEM_PATH_TEST); + assert_eq!( + private_key_str, + Wallet::get_wallet_keys_pem(ALICE_PEM_PATH_TEST).0 + ); + + fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); +} From dbca030977779beddf38332f0da6a2d256fd5f67 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 22 Aug 2024 11:30:31 +0300 Subject: [PATCH 21/52] tests fixed --- sdk/core/tests/wallet_test.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sdk/core/tests/wallet_test.rs b/sdk/core/tests/wallet_test.rs index 4d523d57d5..103166e430 100644 --- a/sdk/core/tests/wallet_test.rs +++ b/sdk/core/tests/wallet_test.rs @@ -4,11 +4,9 @@ use multiversx_sdk::{crypto::public_key::PublicKey, data::address::Address, wall use std::fs::{self, File}; use std::io::Write; -// use multiversx_sc_meta::cmd::wallet::generate_pem_content; -// use multiversx_sc_snippets::{hex, imports::Wallet}; - const ALICE_PEM_PATH: &str = "tests/alice.pem"; -const ALICE_KEYSTORE_PATH_TEST: &str = "tests/alice.json"; +const ALICE_KEYSTORE_PATH_TEST_1: &str = "tests/alice1.json"; +const ALICE_KEYSTORE_PATH_TEST_2: &str = "tests/alice2.json"; const ALICE_PEM_PATH_TEST: &str = "tests/alice_test.pem"; const KEYSTORE_PASSWORD: &str = "abcd"; const ALICE_PUBLIC_KEY: &str = "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1"; @@ -66,7 +64,7 @@ fn write_to_file(content: &str, file: &str) { file.write_all(content.as_bytes()).unwrap(); } -fn create_keystore_file_from_scratch() -> Address { +fn create_keystore_file_from_scratch(file: &str) -> Address { let wallet = Wallet::from_private_key(ALICE_PRIVATE_KEY).unwrap(); let address = wallet.address(); @@ -78,29 +76,29 @@ fn create_keystore_file_from_scratch() -> Address { ALICE_PUBLIC_KEY, KEYSTORE_PASSWORD, ); - write_to_file(&json_result, ALICE_KEYSTORE_PATH_TEST); + write_to_file(&json_result, file); address } #[test] fn test_wallet_convert_pem_to_keystore() { - let _ = create_keystore_file_from_scratch(); + let _ = create_keystore_file_from_scratch(ALICE_KEYSTORE_PATH_TEST_1); let (private_key_pem, _public_key_pem) = Wallet::get_wallet_keys_pem(ALICE_PEM_PATH); assert_eq!( - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST_1, KEYSTORE_PASSWORD) .unwrap() .to_string(), private_key_pem ); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST_1).unwrap(); } #[test] fn test_wallet_convert_keystore_to_pem() { - let address = create_keystore_file_from_scratch(); + let address = create_keystore_file_from_scratch(ALICE_KEYSTORE_PATH_TEST_2); let private_key = - Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST, KEYSTORE_PASSWORD) + Wallet::get_private_key_from_keystore_secret(ALICE_KEYSTORE_PATH_TEST_2, KEYSTORE_PASSWORD) .unwrap(); let private_key_str = private_key.to_string(); let public_key = PublicKey::from(&private_key); @@ -114,5 +112,5 @@ fn test_wallet_convert_keystore_to_pem() { ); fs::remove_file(ALICE_PEM_PATH_TEST).unwrap(); - fs::remove_file(ALICE_KEYSTORE_PATH_TEST).unwrap(); + fs::remove_file(ALICE_KEYSTORE_PATH_TEST_2).unwrap(); } From fe2ef22db0e59c5450b6ef7c9191ae124df634cc Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 14:55:24 +0200 Subject: [PATCH 22/52] multisig whitebox migration --- .../multisig/tests/multisig_whitebox_test.rs | 929 ++++++++---------- 1 file changed, 426 insertions(+), 503 deletions(-) diff --git a/contracts/examples/multisig/tests/multisig_whitebox_test.rs b/contracts/examples/multisig/tests/multisig_whitebox_test.rs index 904a03c7e0..5e1347d82b 100644 --- a/contracts/examples/multisig/tests/multisig_whitebox_test.rs +++ b/contracts/examples/multisig/tests/multisig_whitebox_test.rs @@ -10,11 +10,11 @@ use multisig::{ user_role::UserRole, Multisig, }; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const PROPOSER_ADDRESS_EXPR: &str = "address:proposer"; -const BOARD_MEMBER_ADDRESS_EXPR: &str = "address:board-member"; -const MULTISIG_ADDRESS_EXPR: &str = "sc:multisig"; -const MULTISIG_PATH_EXPR: &str = "mxsc:output/multisig.mxsc.json"; +const OWNER_ADDRESS: TestAddress = TestAddress::new("owner"); +const PROPOSER_ADDRESS: TestAddress = TestAddress::new("proposer"); +const BOARD_MEMBER_ADDRESS: TestAddress = TestAddress::new("board-member"); +const MULTISIG_ADDRESS: TestSCAddress = TestSCAddress::new("multisig"); +const MULTISIG_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/multisig.mxsc.json"); const QUORUM_SIZE: usize = 1; type RustBigUint = num_bigint::BigUint; @@ -59,40 +59,28 @@ fn world() -> ScenarioWorld { fn setup() -> ScenarioWorld { // setup let mut world = world(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - let multisig_code = world.code_expression(MULTISIG_PATH_EXPR); - - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(OWNER_ADDRESS_EXPR, 1, MULTISIG_ADDRESS_EXPR) - .put_account( - PROPOSER_ADDRESS_EXPR, - Account::new().nonce(1).balance(100_000_000u64), - ) - .put_account(BOARD_MEMBER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + + world.account(OWNER_ADDRESS).nonce(1); + world + .account(PROPOSER_ADDRESS) + .nonce(1) + .balance(100_000_000u64); + world.account(BOARD_MEMBER_ADDRESS).nonce(1); // init multisig - world.whitebox_deploy( - &multisig_whitebox, - ScDeployStep::new() - .from(OWNER_ADDRESS_EXPR) - .code(multisig_code), - |sc| { + world + .tx() + .from(OWNER_ADDRESS) + .raw_deploy() + .code(MULTISIG_PATH_EXPR) + .new_address(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let mut board_members = ManagedVec::new(); - board_members.push(managed_address!(&address_expr_to_address( - BOARD_MEMBER_ADDRESS_EXPR - ))); + board_members.push(BOARD_MEMBER_ADDRESS.to_managed_address()); sc.init(QUORUM_SIZE, board_members.into()); - sc.change_user_role( - 0, - managed_address!(&address_expr_to_address(PROPOSER_ADDRESS_EXPR)), - UserRole::Proposer, - ); - }, - ); + sc.change_user_role(0, PROPOSER_ADDRESS.to_managed_address(), UserRole::Proposer); + }); world } @@ -119,70 +107,66 @@ fn call_propose( let mut action_id = 0; - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(PROPOSER_ADDRESS_EXPR) - .egld_value(amount_rust_biguint) - .no_expect(), - |sc| { - action_id = match action { - ActionRaw::_Nothing => panic!("Invalid action"), - ActionRaw::AddBoardMember(addr) => { - sc.propose_add_board_member(managed_address!(&addr)) + let mut transaction = world + .tx() + .from(PROPOSER_ADDRESS) + .to(MULTISIG_ADDRESS) + .egld(BigUint::from(egld_amount)); + + let mut transaction_with_err = match expected_message { + Some(message) => transaction.returns(ExpectError(4u64, message)), + None => transaction.returns(ExpectError(0u64, "")), + }; + + transaction_with_err.whitebox(multisig::contract_obj, |sc| { + action_id = match action { + ActionRaw::_Nothing => panic!("Invalid action"), + ActionRaw::AddBoardMember(addr) => sc.propose_add_board_member(managed_address!(&addr)), + ActionRaw::AddProposer(addr) => sc.propose_add_proposer(managed_address!(&addr)), + ActionRaw::RemoveUser(addr) => sc.propose_remove_user(managed_address!(&addr)), + ActionRaw::ChangeQuorum(new_size) => sc.propose_change_quorum(new_size), + ActionRaw::SendTransferExecute(call_data) => sc.propose_transfer_execute( + managed_address!(&call_data.to), + call_data.egld_amount.into(), + FunctionCall { + function_name: call_data.endpoint_name.into(), + arg_buffer: call_data.arguments.into(), }, - ActionRaw::AddProposer(addr) => sc.propose_add_proposer(managed_address!(&addr)), - ActionRaw::RemoveUser(addr) => sc.propose_remove_user(managed_address!(&addr)), - ActionRaw::ChangeQuorum(new_size) => sc.propose_change_quorum(new_size), - ActionRaw::SendTransferExecute(call_data) => sc.propose_transfer_execute( - managed_address!(&call_data.to), - BigUint::from_bytes_be(&call_data.egld_amount.to_bytes_be()), - FunctionCall { - function_name: call_data.endpoint_name.into(), - arg_buffer: call_data.arguments.into(), - }, - ), - ActionRaw::SendAsyncCall(call_data) => sc.propose_async_call( - managed_address!(&call_data.to), - BigUint::from_bytes_be(&call_data.egld_amount.to_bytes_be()), - FunctionCall { - function_name: call_data.endpoint_name.into(), - arg_buffer: call_data.arguments.into(), - }, - ), - ActionRaw::SCDeployFromSource { - amount, - source, - code_metadata, - arguments, - } => sc.propose_sc_deploy_from_source( - BigUint::from_bytes_be(&amount.to_bytes_be()), - managed_address!(&source), - code_metadata, - boxed_bytes_vec_to_managed(arguments).into(), - ), - ActionRaw::SCUpgradeFromSource { - sc_address, - amount, - source, - code_metadata, - arguments, - } => sc.propose_sc_upgrade_from_source( - managed_address!(&sc_address), - BigUint::from_bytes_be(&amount.to_bytes_be()), - managed_address!(&source), - code_metadata, - boxed_bytes_vec_to_managed(arguments).into(), - ), - } - }, - |r| match expected_message { - Some(msg) => r.assert_user_error(msg), - None => r.assert_ok(), - }, - ); + ), + ActionRaw::SendAsyncCall(call_data) => sc.propose_async_call( + managed_address!(&call_data.to), + call_data.egld_amount.into(), + FunctionCall { + function_name: call_data.endpoint_name.into(), + arg_buffer: call_data.arguments.into(), + }, + ), + ActionRaw::SCDeployFromSource { + amount, + source, + code_metadata, + arguments, + } => sc.propose_sc_deploy_from_source( + amount.into(), + managed_address!(&source), + code_metadata, + boxed_bytes_vec_to_managed(arguments).into(), + ), + ActionRaw::SCUpgradeFromSource { + sc_address, + amount, + source, + code_metadata, + arguments, + } => sc.propose_sc_upgrade_from_source( + managed_address!(&sc_address), + amount.into(), + managed_address!(&source), + code_metadata, + boxed_bytes_vec_to_managed(arguments).into(), + ), + } + }); action_id } @@ -190,341 +174,300 @@ fn call_propose( #[test] fn test_add_board_member() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - const NEW_BOARD_MEMBER_ADDRESS_EXPR: &str = "address:new-board-member"; - world.set_state_step( - SetStateStep::new().put_account(NEW_BOARD_MEMBER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_BOARD_MEMBER_ADDRESS: TestAddress = TestAddress::new("new-board-member"); + world.account(NEW_BOARD_MEMBER_ADDRESS).nonce(1); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role before - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_BOARD_MEMBER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::None); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role before + let user_role = sc.user_role(NEW_BOARD_MEMBER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::None); + }); let action_id = call_propose( &mut world, - ActionRaw::AddBoardMember(address_expr_to_address(NEW_BOARD_MEMBER_ADDRESS_EXPR)), + ActionRaw::AddBoardMember(NEW_BOARD_MEMBER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role after - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_BOARD_MEMBER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::BoardMember); - - let board_members = sc.get_all_board_members().to_vec(); - assert_eq!( - (board_members.get(0).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(BOARD_MEMBER_ADDRESS_EXPR)) - ); - assert_eq!( - (board_members.get(1).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(NEW_BOARD_MEMBER_ADDRESS_EXPR)) - ); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role after + let user_role = sc.user_role(NEW_BOARD_MEMBER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::BoardMember); + + let board_members = sc.get_all_board_members().to_vec(); + assert_eq!(*board_members.get(0), BOARD_MEMBER_ADDRESS); + assert_eq!(*board_members.get(1), NEW_BOARD_MEMBER_ADDRESS); + }); } #[test] fn test_add_proposer() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - const NEW_PROPOSER_ADDRESS_EXPR: &str = "address:new-proposer"; - world.set_state_step( - SetStateStep::new().put_account(NEW_PROPOSER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_PROPOSER_ADDRESS: TestAddress = TestAddress::new("new-proposer"); + world.account(NEW_PROPOSER_ADDRESS).nonce(1); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role before - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::None); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role before + let user_role = sc.user_role(NEW_PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::None); + }); let action_id = call_propose( &mut world, - ActionRaw::AddProposer(address_expr_to_address(NEW_PROPOSER_ADDRESS_EXPR)), + ActionRaw::AddProposer(NEW_PROPOSER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role after - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - NEW_PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::Proposer); - - let proposers = sc.get_all_proposers().to_vec(); - assert_eq!( - (proposers.get(0).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(PROPOSER_ADDRESS_EXPR)) - ); - assert_eq!( - (proposers.get(1).borrow() as &ManagedAddress).clone(), - managed_address!(&address_expr_to_address(NEW_PROPOSER_ADDRESS_EXPR)) - ); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role after + let user_role = sc.user_role(NEW_PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::Proposer); + + let proposers = sc.get_all_proposers().to_vec(); + assert_eq!(*proposers.get(0), PROPOSER_ADDRESS); + assert_eq!(*proposers.get(1), NEW_PROPOSER_ADDRESS); + }); } #[test] fn test_remove_proposer() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - world.whitebox_query(&multisig_whitebox, |sc| { - // check role before - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::Proposer); - }); + + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role before + let user_role = sc.user_role(PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::Proposer); + }); let action_id = call_propose( &mut world, - ActionRaw::RemoveUser(address_expr_to_address(PROPOSER_ADDRESS_EXPR)), + ActionRaw::RemoveUser(PROPOSER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&multisig_whitebox, |sc| { - // check role after - let user_role = sc.user_role(managed_address!(&address_expr_to_address( - PROPOSER_ADDRESS_EXPR - ))); - assert_eq!(user_role, UserRole::None); - - let proposers = sc.get_all_proposers().to_vec(); - assert!(proposers.is_empty()); - }); + world + .query() + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { + // check role after + let user_role = sc.user_role(PROPOSER_ADDRESS.to_managed_address()); + assert_eq!(user_role, UserRole::None); + + let proposers = sc.get_all_proposers(); + assert!(proposers.is_empty()); + }); } #[test] fn test_try_remove_all_board_members() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); let action_id = call_propose( &mut world, - ActionRaw::RemoveUser(address_expr_to_address(BOARD_MEMBER_ADDRESS_EXPR)), + ActionRaw::RemoveUser(BOARD_MEMBER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError(4u64, "quorum cannot exceed board size")) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - |r| { - r.assert_user_error("quorum cannot exceed board size"); - }, - ); + }); } #[test] fn test_change_quorum() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); let new_quorum_size = 2; // try change quorum > board size let action_id = call_propose(&mut world, ActionRaw::ChangeQuorum(new_quorum_size), None); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError(4u64, "quorum cannot exceed board size")) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - |r| { - r.assert_user_error("quorum cannot exceed board size"); - }, - ); + }); // try discard before unsigning - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { - sc.discard_action(action_id); - }, - |r| { - r.assert_user_error("cannot discard action with valid signatures"); - }, - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError( + 4u64, + "cannot discard action with valid signatures", + )) + .whitebox(multisig::contract_obj, |sc| sc.discard_action(action_id)); // unsign and discard action - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.unsign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.unsign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { - sc.discard_action(action_id); - }, - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.discard_action(action_id)); // try sign discarded action - world.whitebox_call_check( - &multisig_whitebox, - ScCallStep::new() - .from(BOARD_MEMBER_ADDRESS_EXPR) - .no_expect(), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .returns(ExpectError(4u64, "action does not exist")) + .whitebox(multisig::contract_obj, |sc| { sc.sign(action_id); - }, - |r| { - r.assert_user_error("action does not exist"); - }, - ); + }); // add another board member - const NEW_BOARD_MEMBER_ADDRESS_EXPR: &str = "address:new-board-member"; - world.set_state_step( - SetStateStep::new().put_account(NEW_BOARD_MEMBER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_BOARD_MEMBER_ADDRESS: TestAddress = TestAddress::new("new-board-member"); + world.account(NEW_BOARD_MEMBER_ADDRESS).nonce(1); let action_id = call_propose( &mut world, - ActionRaw::AddBoardMember(address_expr_to_address(NEW_BOARD_MEMBER_ADDRESS_EXPR)), + ActionRaw::AddBoardMember(NEW_BOARD_MEMBER_ADDRESS.to_address()), None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); // change quorum to 2 let action_id = call_propose(&mut world, ActionRaw::ChangeQuorum(new_quorum_size), None); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); } #[test] fn test_transfer_execute_to_user() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - const NEW_USER_ADDRESS_EXPR: &str = "address:new-user"; - world.set_state_step( - SetStateStep::new().put_account(NEW_USER_ADDRESS_EXPR, Account::new().nonce(1)), - ); + const NEW_USER_ADDRESS: TestAddress = TestAddress::new("new-user"); + world.account(NEW_USER_ADDRESS).nonce(1); const EGLD_AMOUNT: u64 = 100; - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new() - .from(PROPOSER_ADDRESS_EXPR) - .egld_value(EGLD_AMOUNT), - |sc| { + world + .tx() + .from(PROPOSER_ADDRESS) + .to(MULTISIG_ADDRESS) + .egld(EGLD_AMOUNT) + .whitebox(multisig::contract_obj, |sc| { sc.deposit(); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - MULTISIG_ADDRESS_EXPR, - CheckAccount::new().balance(EGLD_AMOUNT.to_string().as_str()), - )); + world.check_account(MULTISIG_ADDRESS).balance(EGLD_AMOUNT); // failed attempt let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(NEW_USER_ADDRESS_EXPR), + to: NEW_USER_ADDRESS.to_address(), egld_amount: rust_biguint!(0), endpoint_name: BoxedBytes::empty(), arguments: Vec::new(), @@ -536,7 +479,7 @@ fn test_transfer_execute_to_user() { let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(NEW_USER_ADDRESS_EXPR), + to: NEW_USER_ADDRESS.to_address(), egld_amount: rust_biguint!(EGLD_AMOUNT), endpoint_name: BoxedBytes::empty(), arguments: Vec::new(), @@ -544,59 +487,48 @@ fn test_transfer_execute_to_user() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.check_state_step(CheckStateStep::new().put_account( - NEW_USER_ADDRESS_EXPR, - CheckAccount::new().balance(EGLD_AMOUNT.to_string().as_str()), - )); + world.check_account(NEW_USER_ADDRESS).balance(EGLD_AMOUNT); } #[test] fn test_transfer_execute_sc_all() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - let adder_whitebox = WhiteboxContract::new(ADDER_ADDRESS_EXPR, adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - const ADDER_OWNER_ADDRESS_EXPR: &str = "address:adder-owner"; - const ADDER_ADDRESS_EXPR: &str = "sc:adder"; - const ADDER_PATH_EXPR: &str = "mxsc:test-contracts/adder.mxsc.json"; + const ADDER_OWNER_ADDRESS: TestAddress = TestAddress::new("adder-owner"); + const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); + const ADDER_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/adder.mxsc.json"); world.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(ADDER_OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(ADDER_OWNER_ADDRESS_EXPR, 1, ADDER_ADDRESS_EXPR), - ); + world.account(ADDER_OWNER_ADDRESS).nonce(1); - world.whitebox_deploy( - &adder_whitebox, - ScDeployStep::new() - .from(ADDER_OWNER_ADDRESS_EXPR) - .code(adder_code), - |sc| { - sc.init(managed_biguint!(5)); - }, - ); + world + .tx() + .raw_deploy() + .from(ADDER_OWNER_ADDRESS) + .code(ADDER_PATH_EXPR) + .new_address(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(ADDER_ADDRESS_EXPR), + to: ADDER_ADDRESS.to_address(), egld_amount: 0u64.into(), endpoint_name: BoxedBytes::from(&b"add"[..]), arguments: vec![BoxedBytes::from(&[5u8][..])], @@ -604,60 +536,55 @@ fn test_transfer_execute_sc_all() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&adder_whitebox, |sc| { - let actual_sum = sc.sum().get(); - let expected_sum = managed_biguint!(10); - assert_eq!(actual_sum, expected_sum); - }); + world + .query() + .to(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + let actual_sum = sc.sum().get(); + let expected_sum = managed_biguint!(10); + assert_eq!(actual_sum, expected_sum); + }); } #[test] fn test_async_call_to_sc() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); - - let adder_whitebox = WhiteboxContract::new(ADDER_ADDRESS_EXPR, adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - const ADDER_OWNER_ADDRESS_EXPR: &str = "address:adder-owner"; - const ADDER_ADDRESS_EXPR: &str = "sc:adder"; - const ADDER_PATH_EXPR: &str = "mxsc:test-contracts/adder.mxsc.json"; + const ADDER_OWNER_ADDRESS: TestAddress = TestAddress::new("adder-owner"); + const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); + const ADDER_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/adder.mxsc.json"); world.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(ADDER_OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(ADDER_OWNER_ADDRESS_EXPR, 1, ADDER_ADDRESS_EXPR), - ); + world.account(ADDER_OWNER_ADDRESS).nonce(1); - world.whitebox_deploy( - &adder_whitebox, - ScDeployStep::new() - .from(ADDER_OWNER_ADDRESS_EXPR) - .code(adder_code), - |sc| { - sc.init(managed_biguint!(5)); - }, - ); + world + .tx() + .raw_deploy() + .from(ADDER_OWNER_ADDRESS) + .code(ADDER_PATH_EXPR) + .new_address(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); let action_id = call_propose( &mut world, ActionRaw::SendAsyncCall(CallActionDataRaw { - to: address_expr_to_address(ADDER_ADDRESS_EXPR), + to: ADDER_ADDRESS.to_address(), egld_amount: 0u64.into(), endpoint_name: BoxedBytes::from(&b"add"[..]), arguments: vec![BoxedBytes::from(&[5u8][..])], @@ -665,93 +592,90 @@ fn test_async_call_to_sc() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&adder_whitebox, |sc| { - let actual_sum = sc.sum().get(); - let expected_sum = managed_biguint!(10); - assert_eq!(actual_sum, expected_sum); - }); + world + .query() + .to(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + let actual_sum = sc.sum().get(); + let expected_sum = managed_biguint!(10); + assert_eq!(actual_sum, expected_sum); + }); } #[test] fn test_deploy_and_upgrade_from_source() { let mut world = setup(); - let multisig_whitebox = WhiteboxContract::new(MULTISIG_ADDRESS_EXPR, multisig::contract_obj); + const NEW_ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("new-adder"); - let adder_whitebox = WhiteboxContract::new(ADDER_ADDRESS_EXPR, adder::contract_obj); - let adder_code = world.code_expression(ADDER_PATH_EXPR); - - let new_adder_whitebox = WhiteboxContract::new(NEW_ADDER_ADDRESS_EXPR, adder::contract_obj); - - const ADDER_OWNER_ADDRESS_EXPR: &str = "address:adder-owner"; - const ADDER_ADDRESS_EXPR: &str = "sc:adder"; - const NEW_ADDER_ADDRESS_EXPR: &str = "sc:new-adder"; - const ADDER_PATH_EXPR: &str = "mxsc:test-contracts/adder.mxsc.json"; + const ADDER_OWNER_ADDRESS: TestAddress = TestAddress::new("adder-owner"); + const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); + const ADDER_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/adder.mxsc.json"); world.register_contract(ADDER_PATH_EXPR, adder::ContractBuilder); - world.set_state_step( - SetStateStep::new() - .put_account(ADDER_OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .new_address(ADDER_OWNER_ADDRESS_EXPR, 1, ADDER_ADDRESS_EXPR) - .new_address(MULTISIG_ADDRESS_EXPR, 0, NEW_ADDER_ADDRESS_EXPR), - ); + world.set_state_step(SetStateStep::new().new_address( + MULTISIG_ADDRESS.eval_to_expr().as_str(), + 0, + NEW_ADDER_ADDRESS.eval_to_expr().as_str(), + )); - world.whitebox_deploy( - &adder_whitebox, - ScDeployStep::new() - .from(ADDER_OWNER_ADDRESS_EXPR) - .code(adder_code), - |sc| { - sc.init(managed_biguint!(5)); - }, - ); + world.account(ADDER_OWNER_ADDRESS).nonce(1); + + world + .tx() + .raw_deploy() + .from(ADDER_OWNER_ADDRESS) + .code(ADDER_PATH_EXPR) + .new_address(ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + sc.init(BigUint::from(5u64)); + }); let action_id = call_propose( &mut world, ActionRaw::SCDeployFromSource { amount: 0u64.into(), - source: address_expr_to_address(ADDER_ADDRESS_EXPR), + source: ADDER_ADDRESS.to_address(), code_metadata: CodeMetadata::all(), arguments: vec![BoxedBytes::from(&[5u8][..])], }, None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - let mut addr = Address::zero(); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let opt_address = sc.perform_action_endpoint(action_id); - addr = opt_address.into_option().unwrap().to_address(); - }, - ); + let addr = opt_address.into_option().unwrap().to_address(); - assert_eq!(address_expr_to_address(NEW_ADDER_ADDRESS_EXPR), addr); + assert_eq!(NEW_ADDER_ADDRESS.to_address(), addr); + }); let action_id = call_propose( &mut world, ActionRaw::SendTransferExecute(CallActionDataRaw { - to: address_expr_to_address(NEW_ADDER_ADDRESS_EXPR), + to: NEW_ADDER_ADDRESS.to_address(), egld_amount: 0u64.into(), endpoint_name: BoxedBytes::from(&b"add"[..]), arguments: vec![BoxedBytes::from(&[5u8][..])], @@ -759,71 +683,70 @@ fn test_deploy_and_upgrade_from_source() { None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); + }); - world.whitebox_query(&new_adder_whitebox, |sc| { - let actual_sum = sc.sum().get(); - let expected_sum = managed_biguint!(10); - assert_eq!(actual_sum, expected_sum); - }); - - let factorial_code = world.code_expression(FACTORIAL_PATH_EXPR); + world + .query() + .to(NEW_ADDER_ADDRESS) + .whitebox(adder::contract_obj, |sc| { + let actual_sum = sc.sum().get(); + let expected_sum = managed_biguint!(10); + assert_eq!(actual_sum, expected_sum); + }); - const FACTORIAL_ADDRESS_EXPR: &str = "sc:factorial"; - const FACTORIAL_PATH_EXPR: &str = "mxsc:test-contracts/factorial.mxsc.json"; + const FACTORIAL_ADDRESS: TestSCAddress = TestSCAddress::new("factorial"); + const FACTORIAL_PATH_EXPR: MxscPath = MxscPath::new("mxsc:test-contracts/factorial.mxsc.json"); world.register_contract(FACTORIAL_PATH_EXPR, factorial::ContractBuilder); - world.set_state_step(SetStateStep::new().put_account( - FACTORIAL_ADDRESS_EXPR, - Account::new().nonce(1).code(factorial_code.clone()), - )); + world + .tx() + .raw_deploy() + .from(OWNER_ADDRESS) + .code(FACTORIAL_PATH_EXPR) + .new_address(FACTORIAL_ADDRESS) + .whitebox(factorial::contract_obj, |sc| { + sc.init(); + }); let action_id = call_propose( &mut world, ActionRaw::SCUpgradeFromSource { - source: address_expr_to_address(FACTORIAL_ADDRESS_EXPR), + source: FACTORIAL_ADDRESS.to_address(), amount: 0u64.into(), code_metadata: CodeMetadata::all(), arguments: Vec::new(), - sc_address: address_expr_to_address(ADDER_ADDRESS_EXPR), + sc_address: ADDER_ADDRESS.to_address(), }, None, ); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| sc.sign(action_id), - ); + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| sc.sign(action_id)); - world.whitebox_call( - &multisig_whitebox, - ScCallStep::new().from(BOARD_MEMBER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(BOARD_MEMBER_ADDRESS) + .to(MULTISIG_ADDRESS) + .whitebox(multisig::contract_obj, |sc| { let _ = sc.perform_action_endpoint(action_id); - }, - ); - - world.check_state_step( - CheckStateStep::new() - .put_account(ADDER_ADDRESS_EXPR, CheckAccount::new().code(factorial_code)), - ); -} + }); -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world.check_account(ADDER_ADDRESS).code(FACTORIAL_PATH_EXPR); } fn boxed_bytes_vec_to_managed( From 1de1b5b6f5981fbadf17b383689750f3a9838e9b Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 15:23:04 +0200 Subject: [PATCH 23/52] impl new crypto opcodes --- framework/base/src/api/crypto_api.rs | 21 +++++++++++ .../api/uncallable/crypto_api_uncallable.rs | 27 ++++++++++++++ .../src/api/core_api_vh/crypto_api_vh.rs | 27 ++++++++++++++ .../wasm-adapter/src/api/crypto_api_node.rs | 37 +++++++++++++++++++ 4 files changed, 112 insertions(+) diff --git a/framework/base/src/api/crypto_api.rs b/framework/base/src/api/crypto_api.rs index 3c5c374a87..235e44919a 100644 --- a/framework/base/src/api/crypto_api.rs +++ b/framework/base/src/api/crypto_api.rs @@ -76,4 +76,25 @@ pub trait CryptoApiImpl: ManagedTypeApiImpl { s: Self::ManagedBufferHandle, dest: Self::ManagedBufferHandle, ); + + fn verify_secp256r1_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool; + + fn verify_bls_signature_share_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool; + + fn verify_bls_aggregated_signature_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool; } diff --git a/framework/base/src/api/uncallable/crypto_api_uncallable.rs b/framework/base/src/api/uncallable/crypto_api_uncallable.rs index 59195618c9..bb42aa04bb 100644 --- a/framework/base/src/api/uncallable/crypto_api_uncallable.rs +++ b/framework/base/src/api/uncallable/crypto_api_uncallable.rs @@ -82,4 +82,31 @@ impl CryptoApiImpl for UncallableApi { ) { unreachable!() } + + fn verify_secp256r1_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + unreachable!() + } + + fn verify_bls_signature_share_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + unreachable!() + } + + fn verify_bls_aggregated_signature_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + unreachable!() + } } diff --git a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs index f3789181e7..aa4c2dab94 100644 --- a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs +++ b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs @@ -99,4 +99,31 @@ impl CryptoApiImpl for VMHooksApi { ) { panic!("encode_secp256k1_signature not implemented yet!") } + + fn verify_secp256r1_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + panic!("verify_secp256r1 not implemented yet!") + } + + fn verify_bls_signature_share_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + panic!("verify_bls_signature_share not implemented yet!") + } + + fn verify_bls_aggregated_signature_managed( + &self, + _key: Self::ManagedBufferHandle, + _message: Self::ManagedBufferHandle, + _signature: Self::ManagedBufferHandle, + ) -> bool { + panic!("verify_bls_aggregated_signature not implemented yet!") + } } diff --git a/framework/wasm-adapter/src/api/crypto_api_node.rs b/framework/wasm-adapter/src/api/crypto_api_node.rs index eb16e25e6a..0cbe24fad5 100644 --- a/framework/wasm-adapter/src/api/crypto_api_node.rs +++ b/framework/wasm-adapter/src/api/crypto_api_node.rs @@ -25,6 +25,16 @@ extern "C" { ) -> i32; fn managedEncodeSecp256k1DerSignature(rHandle: i32, sHandle: i32, sigHandle: i32) -> i32; + + fn managedVerifySecp256r1(keyHandle: i32, messageHandle: i32, sigHandle: i32) -> i32; + + fn managedVerifyBLSSignatureShare(keyHandle: i32, messageHandle: i32, sigHandle: i32) -> i32; + + fn managedVerifyBLSAggregatedSignature( + keyHandle: i32, + messageHandle: i32, + sigHandle: i32, + ) -> i32; } impl CryptoApi for VmApiImpl { @@ -123,4 +133,31 @@ impl CryptoApiImpl for VmApiImpl { let _ = managedEncodeSecp256k1DerSignature(r, s, dest_sig_handle); } } + + fn verify_secp256r1_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool { + unsafe { managedVerifySecp256r1(key, message, signature) == 0 } + } + + fn verify_bls_signature_share_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool { + unsafe { managedVerifyBLSSignatureShare(key, message, signature) == 0 } + } + + fn verify_bls_aggregated_signature_managed( + &self, + key: Self::ManagedBufferHandle, + message: Self::ManagedBufferHandle, + signature: Self::ManagedBufferHandle, + ) -> bool { + unsafe { managedVerifyBLSAggregatedSignature(key, message, signature) == 0 } + } } From 9543e03aab14eeb01b2e72aec2b6454bae724a78 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 16:30:59 +0200 Subject: [PATCH 24/52] added in crypto wrapper and test contract --- .../basic-features/sc-config.toml | 3 ++ .../basic-features/src/crypto_features.rs | 30 ++++++++++++++ .../basic-features/wasm/src/lib.rs | 7 +++- .../contract_base/wrappers/crypto_wrapper.rs | 39 +++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index 82698d1dab..6b24db99b9 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -1,6 +1,9 @@ [settings] main = "basic-features" +[contracts.basic-features] +ei = "1.4" + [contracts.basic-features.profile] overflow-checks = true # needed for overflow tests diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 56c543163c..2c08b850e5 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -64,4 +64,34 @@ pub trait CryptoFeatures { fn compute_secp256k1_der_signature(&self, r: ManagedBuffer, s: ManagedBuffer) -> ManagedBuffer { self.crypto().encode_secp256k1_der_signature(&r, &s) } + + #[endpoint] + fn verify_secp256r1_signature( + &self, + key: ManagedBuffer, + message: ManagedBuffer, + signature: ManagedBuffer, + ) -> bool { + self.crypto().verify_secp256r1(&key, &message, &signature) + } + #[endpoint] + fn verify_bls_signature_share_managed( + &self, + key: ManagedBuffer, + message: ManagedBuffer, + signature: ManagedBuffer, + ) -> bool { + self.crypto() + .verify_bls_signature_share(&key, &message, &signature) + } + #[endpoint] + fn verify_bls_aggregated_signature_managed( + &self, + key: ManagedBuffer, + message: ManagedBuffer, + signature: ManagedBuffer, + ) -> bool { + self.crypto() + .verify_bls_aggregated_signature(&key, &message, &signature) + } } diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index 887b75bcd5..c602f6e198 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 403 +// Endpoints: 406 // Async Callback: 1 -// Total number of exported functions: 405 +// Total number of exported functions: 408 #![no_std] @@ -145,6 +145,9 @@ multiversx_sc_wasm_adapter::endpoints! { verify_secp256k1_signature => verify_secp256k1_signature verify_custom_secp256k1_signature => verify_custom_secp256k1_signature compute_secp256k1_der_signature => compute_secp256k1_der_signature + verify_secp256r1_signature => verify_secp256r1_signature + verify_bls_signature_share_managed => verify_bls_signature_share_managed + verify_bls_aggregated_signature_managed => verify_bls_aggregated_signature_managed echo_u64 => echo_u64 echo_i64 => echo_i64 echo_i32 => echo_i32 diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index c314899eaa..76b8fcd996 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -129,4 +129,43 @@ where ); ManagedBuffer::from_handle(new_handle) } + + pub fn verify_secp256r1( + &self, + key: &ManagedBuffer, + message: &ManagedBuffer, + signature: &ManagedBuffer, + ) -> bool { + A::crypto_api_impl().verify_secp256r1_managed( + key.get_handle(), + message.get_handle(), + signature.get_handle(), + ) + } + + pub fn verify_bls_signature_share( + &self, + key: &ManagedBuffer, + message: &ManagedBuffer, + signature: &ManagedBuffer, + ) -> bool { + A::crypto_api_impl().verify_bls_signature_share_managed( + key.get_handle(), + message.get_handle(), + signature.get_handle(), + ) + } + + pub fn verify_bls_aggregated_signature( + &self, + key: &ManagedBuffer, + message: &ManagedBuffer, + signature: &ManagedBuffer, + ) -> bool { + A::crypto_api_impl().verify_bls_aggregated_signature_managed( + key.get_handle(), + message.get_handle(), + signature.get_handle(), + ) + } } From 3fc082a04f42d54f7c9bebb764c9485266708221 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 22 Aug 2024 17:30:17 +0200 Subject: [PATCH 25/52] added tests --- .../scenarios/crypto_verify_bls.scen.json | 52 +++++++- .../crypto_verify_secp256r1.scen.json | 121 ++++++++++++++++++ .../basic-features/src/crypto_features.rs | 6 +- .../tests/basic_features_scenario_go_test.rs | 5 + .../tests/basic_features_scenario_rs_test.rs | 6 + .../basic-features/wasm/src/lib.rs | 4 +- 6 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index ead18354dc..7b07232695 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -41,6 +41,56 @@ "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "4", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_signature_share", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "5", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json new file mode 100644 index 0000000000..e87822db95 --- /dev/null +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -0,0 +1,121 @@ +{ + "name": "crypto", + "comment": "", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:basic-features": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/basic-features.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "5 - compressed key", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_secp256r1_signature", + "arguments": [ + "0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5", + "0x6d65737361676520746f207369676e", + "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "6 - uncompressed key", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_secp256r1_signature", + "arguments": [ + "0x04a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5ca1d22fe57c6103dbaac10cf15d15c0791cab8bb9a04f800e4d215276cb3e008", + "0x6d65737361676520746f207369676e", + "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "7 - encode key from r and s", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "compute_secp256k1_der_signature", + "arguments": [ + "0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998", + "0x4a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "8 - verify custom secp256k1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_custom_secp256k1_signature", + "arguments": [ + "0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652", + "0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", + "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93", + "0" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 2c08b850e5..f66479026c 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -74,8 +74,9 @@ pub trait CryptoFeatures { ) -> bool { self.crypto().verify_secp256r1(&key, &message, &signature) } + #[endpoint] - fn verify_bls_signature_share_managed( + fn verify_bls_signature_share( &self, key: ManagedBuffer, message: ManagedBuffer, @@ -84,8 +85,9 @@ pub trait CryptoFeatures { self.crypto() .verify_bls_signature_share(&key, &message, &signature) } + #[endpoint] - fn verify_bls_aggregated_signature_managed( + fn verify_bls_aggregated_signature( &self, key: ManagedBuffer, message: ManagedBuffer, diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs index 9c39d06ae5..f5a9a10726 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs @@ -94,6 +94,11 @@ fn crypto_verify_secp_256_k_1_go() { world().run("scenarios/crypto_verify_secp256k1.scen.json"); } +#[test] +fn crypto_verify_secp_256_r_1_go() { + world().run("scenarios/crypto_verify_secp256r1.scen.json"); +} + #[test] fn echo_array_u_8_go() { world().run("scenarios/echo_array_u8.scen.json"); diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs index f35c4779e6..95a617e20c 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs @@ -109,6 +109,12 @@ fn crypto_verify_secp_256_k_1_rs() { world().run("scenarios/crypto_verify_secp256k1.scen.json"); } +#[test] +#[ignore] +fn crypto_verify_secp_256_r_1_rs() { + world().run("scenarios/crypto_verify_secp256r1.scen.json"); +} + #[test] fn echo_array_u_8_rs() { world().run("scenarios/echo_array_u8.scen.json"); diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index c602f6e198..90986ec90b 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -146,8 +146,8 @@ multiversx_sc_wasm_adapter::endpoints! { verify_custom_secp256k1_signature => verify_custom_secp256k1_signature compute_secp256k1_der_signature => compute_secp256k1_der_signature verify_secp256r1_signature => verify_secp256r1_signature - verify_bls_signature_share_managed => verify_bls_signature_share_managed - verify_bls_aggregated_signature_managed => verify_bls_aggregated_signature_managed + verify_bls_signature_share => verify_bls_signature_share + verify_bls_aggregated_signature => verify_bls_aggregated_signature echo_u64 => echo_u64 echo_i64 => echo_i64 echo_i32 => echo_i32 From 6e59c53c981f86059622da9d4eba376f03e294f1 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 23 Aug 2024 15:33:53 +0200 Subject: [PATCH 26/52] created contract variant from new crypto endpoints --- .../basic-features/sc-config.toml | 11 ++++++ .../wasm-basic-features-crypto/Cargo.toml | 35 +++++++++++++++++++ .../wasm-basic-features-crypto/src/lib.rs | 27 ++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml create mode 100644 contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index 6b24db99b9..b21719850f 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -12,6 +12,17 @@ add-unlabelled = false add-endpoints = ["init", "load_bytes", "store_bytes"] kill_legacy_callback = true +[contracts.basic-features-crypto] +ei = "1.4" +add-unlabelled = false +add-endpoints = [ + "init", + "verify_secp256r1_signature", + "verify_bls_signature_share", + "verify_bls_aggregated_signature", +] +kill_legacy_callback = true + [[proxy]] path = "src/basic_features_proxy.rs" add-unlabelled = false diff --git a/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml new file mode 100644 index 0000000000..46f40289e3 --- /dev/null +++ b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.toml @@ -0,0 +1,35 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + +[package] +name = "basic-features-crypto-wasm" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] + +[profile.release] +codegen-units = 1 +opt-level = "z" +lto = true +debug = false +panic = "abort" +overflow-checks = false + +[profile.dev] +panic = "abort" + +[dependencies.basic-features] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "0.52.3" +path = "../../../../framework/wasm-adapter" + +[workspace] +members = ["."] diff --git a/contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs new file mode 100644 index 0000000000..134138a65f --- /dev/null +++ b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/src/lib.rs @@ -0,0 +1,27 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Endpoints: 3 +// Async Callback (empty): 1 +// Total number of exported functions: 5 + +#![no_std] + +multiversx_sc_wasm_adapter::allocator!(); +multiversx_sc_wasm_adapter::panic_handler!(); + +multiversx_sc_wasm_adapter::endpoints! { + basic_features + ( + init => init + verify_secp256r1_signature => verify_secp256r1_signature + verify_bls_signature_share => verify_bls_signature_share + verify_bls_aggregated_signature => verify_bls_aggregated_signature + ) +} + +multiversx_sc_wasm_adapter::async_callback_empty! {} From 97c63ab5f81283313f99412902236d8320862a6a Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 23 Aug 2024 17:12:25 +0300 Subject: [PATCH 27/52] basic features sc-config fix --- .../basic-features/sc-config.toml | 9 +- .../basic-features/src/crypto_features.rs | 3 + .../wasm-basic-features-crypto/Cargo.lock | 186 ++++++++++++++++++ .../basic-features/wasm/src/lib.rs | 7 +- 4 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index b21719850f..42c4880f67 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -2,7 +2,6 @@ main = "basic-features" [contracts.basic-features] -ei = "1.4" [contracts.basic-features.profile] overflow-checks = true # needed for overflow tests @@ -15,12 +14,8 @@ kill_legacy_callback = true [contracts.basic-features-crypto] ei = "1.4" add-unlabelled = false -add-endpoints = [ - "init", - "verify_secp256r1_signature", - "verify_bls_signature_share", - "verify_bls_aggregated_signature", -] +add-endpoints = ["init"] +add-labels = ["crypto-ei-1.4"] kill_legacy_callback = true [[proxy]] diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index f66479026c..4a9c7dbb6f 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -66,6 +66,7 @@ pub trait CryptoFeatures { } #[endpoint] + #[label("crypto-ei-1.4")] fn verify_secp256r1_signature( &self, key: ManagedBuffer, @@ -76,6 +77,7 @@ pub trait CryptoFeatures { } #[endpoint] + #[label("crypto-ei-1.4")] fn verify_bls_signature_share( &self, key: ManagedBuffer, @@ -87,6 +89,7 @@ pub trait CryptoFeatures { } #[endpoint] + #[label("crypto-ei-1.4")] fn verify_bls_aggregated_signature( &self, key: ManagedBuffer, diff --git a/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock new file mode 100644 index 0000000000..1666820785 --- /dev/null +++ b/contracts/feature-tests/basic-features/wasm-basic-features-crypto/Cargo.lock @@ -0,0 +1,186 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "basic-features" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-modules", +] + +[[package]] +name = "basic-features-crypto-wasm" +version = "0.0.0" +dependencies = [ + "basic-features", + "multiversx-sc-wasm-adapter", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "multiversx-sc" +version = "0.52.3" +dependencies = [ + "bitflags", + "hex-literal", + "multiversx-sc-codec", + "multiversx-sc-derive", + "num-traits", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec" +version = "0.20.1" +dependencies = [ + "arrayvec", + "multiversx-sc-codec-derive", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec-derive" +version = "0.20.1" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "multiversx-sc-derive" +version = "0.52.3" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "radix_trie", + "syn", +] + +[[package]] +name = "multiversx-sc-modules" +version = "0.52.3" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "multiversx-sc-wasm-adapter" +version = "0.52.3" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" diff --git a/contracts/feature-tests/basic-features/wasm/src/lib.rs b/contracts/feature-tests/basic-features/wasm/src/lib.rs index 90986ec90b..887b75bcd5 100644 --- a/contracts/feature-tests/basic-features/wasm/src/lib.rs +++ b/contracts/feature-tests/basic-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 406 +// Endpoints: 403 // Async Callback: 1 -// Total number of exported functions: 408 +// Total number of exported functions: 405 #![no_std] @@ -145,9 +145,6 @@ multiversx_sc_wasm_adapter::endpoints! { verify_secp256k1_signature => verify_secp256k1_signature verify_custom_secp256k1_signature => verify_custom_secp256k1_signature compute_secp256k1_der_signature => compute_secp256k1_der_signature - verify_secp256r1_signature => verify_secp256r1_signature - verify_bls_signature_share => verify_bls_signature_share - verify_bls_aggregated_signature => verify_bls_aggregated_signature echo_u64 => echo_u64 echo_i64 => echo_i64 echo_i32 => echo_i32 From e437447b3bd6806ad3989c2186052f5b6918393c Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 23 Aug 2024 18:52:52 +0200 Subject: [PATCH 28/52] test reorg --- .../scenarios/crypto_verify_bls.scen.json | 50 ---------- ..._verify_bls_aggregated_signature.scen.json | 71 ++++++++++++++ .../crypto_verify_bls_share.scen.json | 96 +++++++++++++++++++ .../crypto_verify_secp256r1.scen.json | 74 +++----------- .../tests/basic_features_scenario_go_test.rs | 10 ++ .../tests/basic_features_scenario_rs_test.rs | 16 ++++ 6 files changed, 205 insertions(+), 112 deletions(-) create mode 100644 contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json create mode 100644 contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index 7b07232695..f5c6ef194c 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -41,56 +41,6 @@ "gas": "*", "refund": "*" } - }, - { - "step": "scCall", - "id": "4", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_bls_signature_share", - "arguments": [ - "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", - "0x6d65737361676520746f206265207369676e6564", - "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x01" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "5", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_bls_aggregated_signature", - "arguments": [ - "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", - "0x6d65737361676520746f206265207369676e6564", - "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x01" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } } ] } \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json new file mode 100644 index 0000000000..46617194c5 --- /dev/null +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -0,0 +1,71 @@ +{ + "name": "crypto", + "comment": "does not currently work with scenarios-rs, because verify_bls function is not yet mocked", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:basic-features-crypto": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/basic-features-crypto.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", + "0x6d65737361676530", + "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", + "0x6d657373616765323133", + "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x00" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json new file mode 100644 index 0000000000..046b015d86 --- /dev/null +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -0,0 +1,96 @@ +{ + "name": "crypto", + "comment": "does not currently work with scenarios-rs, because verify_bls function is not yet mocked", + "gasSchedule": "v3", + "steps": [ + { + "step": "setState", + "accounts": { + "sc:basic-features-crypto": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/basic-features-crypto.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_signature_share", + "arguments": [ + "0x3e886a4c6e109a151f4105aee65a5192d150ef1fa68d3cd76964a0b086006dbe4324c989deb0e4416c6d6706db1b1910eb2732f08842fb4886067b9ed191109ac2188d76002d2e11da80a3f0ea89fee6b59c834cc478a6bd49cb8a193b1abb16", + "0xe96bd0f36b70c5ccc0c4396343bd7d8255b8a526c55fa1e218511fafe6539b8e", + "0x04725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features-crypto", + "function": "verify_bls_signature_share", + "arguments": [ + "0x2c9a358953f61d34401d7ee4175eec105c476b18baacab371e2f47270035b539d84ad79ba587552b7e38802be00ff7148fc2a9c7a7034ff1e63ee24602ee952235ad14ca7d36e2be617fb2c99ed22a7a2729d86ae9fbb4df06f957ba07fec50e", + "0x1e46d9cbb995e30b82485525c29f80ac78aca295a6e88a11c3df8f9a445494bb", + "0xbe8c460db180d6254c712ead3aa81935bc9be15b919dd45cb152b3dece04762569778c5e70e7af03fa1c66409d4f4711" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x00" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "2", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_aggregated_signature", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index e87822db95..0de6016ef6 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -6,10 +6,10 @@ { "step": "setState", "accounts": { - "sc:basic-features": { + "sc:basic-features-crypto": { "nonce": "0", "balance": "0", - "code": "mxsc:../output/basic-features.mxsc.json" + "code": "mxsc:../output/basic-features-crypto.mxsc.json" }, "address:an_account": { "nonce": "0", @@ -19,15 +19,15 @@ }, { "step": "scCall", - "id": "5 - compressed key", + "id": "1", "tx": { "from": "address:an_account", - "to": "sc:basic-features", + "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ - "0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5", - "0x6d65737361676520746f207369676e", - "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + "0x03e4d20902182b89cd5ed7984ebcf063f2fd2508d9f034e4109be487be9e2cf54d", + "0xa607fab72e13d6b625942bd5c56cc32792c2c7c7f16053b2fb6d62dd9cf36fdacf9d5a8af3537eaf5eb93335b36cf8f1d6e5bb2dfffce9055a2608d5e1a5b839eacf36dd5dec6d2fa156133acf064cc26487d543873f3b3837a3c09b5f4cb509bbc6585d", + "0xd5065c32582bf0bc8f96b34177cbf47f61d4705d64daaebff884693b6dd94afd50d3ac647aeb14d325c28bb00ab68b23280c1c480cac0e72b5a58176ac8cd1b9" ], "gasLimit": "50,000,000", "gasPrice": "0" @@ -44,14 +44,14 @@ }, { "step": "scCall", - "id": "6 - uncompressed key", + "id": "2", "tx": { "from": "address:an_account", - "to": "sc:basic-features", + "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ "0x04a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5ca1d22fe57c6103dbaac10cf15d15c0791cab8bb9a04f800e4d215276cb3e008", - "0x6d65737361676520746f207369676e", + "0x00", "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" ], "gasLimit": "50,000,000", @@ -59,57 +59,7 @@ }, "expect": { "out": [ - "0x01" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "7 - encode key from r and s", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "compute_secp256k1_der_signature", - "arguments": [ - "0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998", - "0x4a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "8 - verify custom secp256k1", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_custom_secp256k1_signature", - "arguments": [ - "0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652", - "0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", - "0x304502210090f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e5499802204a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93", - "0" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x01" + "0x00" ], "status": "", "logs": "*", @@ -118,4 +68,4 @@ } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs index f5a9a10726..3a7a5dc515 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs @@ -84,6 +84,16 @@ fn crypto_verify_bls_go() { world().run("scenarios/crypto_verify_bls.scen.json"); } +#[test] +fn crypto_verify_bls_share_go() { + world().run("scenarios/crypto_verify_bls_share.scen.json"); +} + +#[test] +fn crypto_verify_bls_aggregated_go() { + world().run("scenarios/crypto_verify_bls_aggregated_signature.scen.json"); +} + #[test] fn crypto_verify_ed_25519_go() { world().run("scenarios/crypto_verify_ed25519.scen.json"); diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs index 95a617e20c..2689d7f3ec 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_rs_test.rs @@ -11,6 +11,10 @@ fn world() -> ScenarioWorld { "mxsc:../esdt-system-sc-mock/output/esdt-system-sc-mock.mxsc.json", esdt_system_sc_mock::ContractBuilder, ); + blockchain.register_contract( + "mxsc:output/basic-features-crypto.mxsc.json", + basic_features::ContractBuilder, + ); blockchain } @@ -98,6 +102,18 @@ fn crypto_verify_bls_rs() { world().run("scenarios/crypto_verify_bls.scen.json"); } +#[test] +#[ignore] +fn crypto_verify_bls_share_rs() { + world().run("scenarios/crypto_verify_bls_share.scen.json"); +} + +#[test] +#[ignore] +fn crypto_verify_bls_aggregated_rs() { + world().run("scenarios/crypto_verify_bls_aggregated_signature.scen.json"); +} + #[test] fn crypto_verify_ed_25519_rs() { world().run("scenarios/crypto_verify_ed25519.scen.json"); From 93ebae93e5d6710b4fe0919eed9ef5f16c392ce5 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 06:31:13 +0300 Subject: [PATCH 29/52] deprecated the older whitebox methods --- .../tests/st_whitebox_deprecated_test.rs | 54 +++++++++++++++++++ .../src/facade/scenario_world_whitebox.rs | 26 +++++++++ 2 files changed, 80 insertions(+) create mode 100644 contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs diff --git a/contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs b/contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs new file mode 100644 index 0000000000..e67fd8cacf --- /dev/null +++ b/contracts/feature-tests/scenario-tester/tests/st_whitebox_deprecated_test.rs @@ -0,0 +1,54 @@ +#![allow(deprecated)] + +use multiversx_sc_scenario::imports::*; +use scenario_tester::*; + +const ADDER_PATH_EXPR: &str = "mxsc:output/scenario-tester.mxsc.json"; + +fn world() -> ScenarioWorld { + let mut blockchain = ScenarioWorld::new(); + + blockchain.register_contract( + "mxsc:output/scenario-tester.mxsc.json", + scenario_tester::ContractBuilder, + ); + blockchain +} + +#[test] +fn st_whitebox() { + let mut world = world(); + let st_whitebox = WhiteboxContract::new("sc:adder", scenario_tester::contract_obj); + let st_code = world.code_expression(ADDER_PATH_EXPR); + + world + .set_state_step( + SetStateStep::new() + .put_account("address:owner", Account::new().nonce(1)) + .new_address("address:owner", 1, "sc:adder"), + ) + .whitebox_deploy( + &st_whitebox, + ScDeployStep::new().from("address:owner").code(st_code), + |sc| { + sc.init(5u32.into()); + }, + ) + .whitebox_query(&st_whitebox, |sc| { + let sum_value = sc.sum(); + assert_eq!(sum_value.get(), 5u32); + }) + .whitebox_call( + &st_whitebox, + ScCallStep::new().from("address:owner"), + |sc| sc.add(3u32.into()), + ) + .check_state_step( + CheckStateStep::new() + .put_account("address:owner", CheckAccount::new()) + .put_account( + "sc:adder", + CheckAccount::new().check_storage("str:sum", "8"), + ), + ); +} diff --git a/framework/scenario/src/facade/scenario_world_whitebox.rs b/framework/scenario/src/facade/scenario_world_whitebox.rs index 32a148ad0a..542e0fe0b2 100644 --- a/framework/scenario/src/facade/scenario_world_whitebox.rs +++ b/framework/scenario/src/facade/scenario_world_whitebox.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] + use multiversx_chain_vm::tx_mock::{TxFunctionName, TxResult}; use multiversx_sc::contract_base::{CallableContract, ContractBase}; @@ -10,6 +12,10 @@ use crate::{ use super::whitebox_contract::WhiteboxContract; impl ScenarioWorld { + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_query( &mut self, whitebox_contract: &WhiteboxContract, @@ -24,6 +30,10 @@ impl ScenarioWorld { }) } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_query_check( &mut self, whitebox_contract: &WhiteboxContract, @@ -50,6 +60,10 @@ impl ScenarioWorld { self } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_call( &mut self, whitebox_contract: &WhiteboxContract, @@ -65,6 +79,10 @@ impl ScenarioWorld { }) } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_call_check( &mut self, whitebox_contract: &WhiteboxContract, @@ -99,6 +117,10 @@ impl ScenarioWorld { self } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_deploy( &mut self, whitebox_contract: &WhiteboxContract, @@ -114,6 +136,10 @@ impl ScenarioWorld { }) } + #[deprecated( + since = "0.53.0", + note = "Please use method `whitebox`, as part of the unified transaction syntax." + )] pub fn whitebox_deploy_check( &mut self, whitebox_contract: &WhiteboxContract, From e9397b00cd56c1ebd677ef6a055063090a84b62f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 06:42:55 +0300 Subject: [PATCH 30/52] price aggregator whitebox migration --- .../tests/price_aggregator_blackbox_test.rs | 51 +++++++++---------- .../tests/price_aggregator_stress_blackbox.rs | 23 +++------ 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs b/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs index b0e1f54455..a312b0ca1f 100644 --- a/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs +++ b/contracts/core/price-aggregator/tests/price_aggregator_blackbox_test.rs @@ -1,6 +1,6 @@ use multiversx_price_aggregator_sc::{ price_aggregator_data::{OracleStatus, TimestampedPrice, TokenPair}, - ContractObj, PriceAggregator, MAX_ROUND_DURATION_SECONDS, + PriceAggregator, MAX_ROUND_DURATION_SECONDS, }; use multiversx_sc_scenario::imports::*; @@ -35,7 +35,6 @@ fn world() -> ScenarioWorld { struct PriceAggregatorTestState { world: ScenarioWorld, oracles: Vec, - price_aggregator_whitebox: WhiteboxContract>, } impl PriceAggregatorTestState { @@ -57,16 +56,7 @@ impl PriceAggregatorTestState { oracles.push(address_value); } - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS, - multiversx_price_aggregator_sc::contract_obj, - ); - - Self { - world, - oracles, - price_aggregator_whitebox, - } + Self { world, oracles } } fn deploy(&mut self) -> &mut Self { @@ -203,9 +193,10 @@ fn test_price_aggregator_submit() { state.submit(&state.oracles[0].clone(), 95, 100); let current_timestamp = 100; - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let token_pair = TokenPair { from: managed_buffer!(EGLD_TICKER), to: managed_buffer!(USD_TICKER), @@ -237,14 +228,15 @@ fn test_price_aggregator_submit() { accepted_submissions: 1 } ); - }); + }, + ); // first oracle submit again - submission not accepted state.submit(&state.oracles[0].clone(), 95, 100); - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { assert_eq!( sc.oracle_status() .get(&managed_address!(&state.oracles[0].to_address())) @@ -254,7 +246,8 @@ fn test_price_aggregator_submit() { accepted_submissions: 1 } ); - }); + }, + ); } #[test] @@ -283,9 +276,9 @@ fn test_price_aggregator_submit_round_ok() { // submit third state.submit(&state.oracles[2].clone(), 105, 12_000); - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let result = sc.latest_price_feed(managed_buffer!(EGLD_TICKER), managed_buffer!(USD_TICKER)); @@ -312,7 +305,8 @@ fn test_price_aggregator_submit_round_ok() { decimals } ); - }); + }, + ); } #[test] @@ -338,9 +332,9 @@ fn test_price_aggregator_discarded_round() { // submit second - this will discard the previous submission state.submit(&state.oracles[1].clone(), current_timestamp - 1, 11_000); - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let token_pair = TokenPair { from: managed_buffer!(EGLD_TICKER), to: managed_buffer!(USD_TICKER), @@ -353,7 +347,8 @@ fn test_price_aggregator_discarded_round() { .unwrap(), managed_biguint!(11_000) ); - }); + }, + ); } #[test] diff --git a/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs b/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs index 660bbf1dda..be457448b5 100644 --- a/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs +++ b/contracts/core/price-aggregator/tests/price_aggregator_stress_blackbox.rs @@ -1,6 +1,6 @@ use multiversx_price_aggregator_sc::{ price_aggregator_data::{OracleStatus, TokenPair}, - ContractObj, PriceAggregator, + PriceAggregator, }; use multiversx_sc_scenario::imports::*; @@ -34,7 +34,6 @@ fn world() -> ScenarioWorld { struct PriceAggregatorTestState { world: ScenarioWorld, oracles: Vec, - price_aggregator_whitebox: WhiteboxContract>, } impl PriceAggregatorTestState { @@ -60,16 +59,7 @@ impl PriceAggregatorTestState { oracles.push(address_value); } - let price_aggregator_whitebox = WhiteboxContract::new( - PRICE_AGGREGATOR_ADDRESS, - multiversx_price_aggregator_sc::contract_obj, - ); - - Self { - world, - oracles, - price_aggregator_whitebox, - } + Self { world, oracles } } fn deploy(&mut self) -> &mut Self { @@ -170,9 +160,9 @@ fn test_price_aggregator_submit() { } let current_timestamp = 100; - state - .world - .whitebox_query(&state.price_aggregator_whitebox, |sc| { + state.world.query().to(PRICE_AGGREGATOR_ADDRESS).whitebox( + multiversx_price_aggregator_sc::contract_obj, + |sc| { let blockchain_timestamp = sc.blockchain().get_block_timestamp(); let token_pair = TokenPair { @@ -207,7 +197,8 @@ fn test_price_aggregator_submit() { } ); } - }); + }, + ); // submit last that resets the round state.submit( From c841e2a6eab8f390675abf4b21ec2b01461ddcba Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 07:16:43 +0300 Subject: [PATCH 31/52] forwarder whitebox migration --- .../tests/forwarder_whitebox_legacy_test.rs | 124 ++++++------------ .../tests/forwarder_whitebox_test.rs | 115 ++++++---------- .../interaction/expr/test_token_identifier.rs | 4 + 3 files changed, 89 insertions(+), 154 deletions(-) diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs index 8766bfa174..f6cfb158f6 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs @@ -1,24 +1,16 @@ use forwarder_legacy::fwd_nft_legacy::{Color, ForwarderNftModule}; -use multiversx_sc::{contract_base::ContractBase, types::Address}; -use multiversx_sc_scenario::{ - managed_address, managed_biguint, managed_token_id, - scenario_model::{ - Account, AddressValue, CheckAccount, CheckStateStep, ScCallStep, SetStateStep, - }, - ScenarioWorld, WhiteboxContract, -}; -const USER_ADDRESS_EXPR: &str = "address:user"; -const FORWARDER_ADDRESS_EXPR: &str = "sc:forwarder_legacy"; -const FORWARDER_PATH_EXPR: &str = "mxsc:output/forwarder_legacy.mxsc.json"; +use multiversx_sc_scenario::imports::*; -const NFT_TOKEN_ID_EXPR: &str = "str:COOL-123456"; -const NFT_TOKEN_ID: &[u8] = b"COOL-123456"; +const USER_ADDRESS: TestAddress = TestAddress::new("user"); +const FORWARDER_ADDRESS: TestSCAddress = TestSCAddress::new("forwarder_legacy"); +const FORWARDER_PATH: MxscPath = MxscPath::new("output/forwarder_legacy.mxsc.json"); +const NFT_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("COOL-123456"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract(FORWARDER_PATH_EXPR, forwarder_legacy::ContractBuilder); + blockchain.register_contract(FORWARDER_PATH, forwarder_legacy::ContractBuilder); blockchain } @@ -26,57 +18,40 @@ fn world() -> ScenarioWorld { fn test_nft_update_attributes_and_send() { let mut world = world(); - let forwarder_legacy_code = world.code_expression(FORWARDER_PATH_EXPR); let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTUpdateAttributes".to_string(), ]; - world.set_state_step( - SetStateStep::new() - .put_account(USER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - FORWARDER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(forwarder_legacy_code) - .esdt_roles(NFT_TOKEN_ID_EXPR, roles), - ), - ); - - let forwarder_legacy_whitebox = - WhiteboxContract::new(FORWARDER_ADDRESS_EXPR, forwarder_legacy::contract_obj); + world.account(USER_ADDRESS).nonce(1); + world + .account(FORWARDER_ADDRESS) + .nonce(1) + .code(FORWARDER_PATH) + .esdt_roles(NFT_TOKEN_ID, roles); let original_attributes = Color { r: 0, g: 0, b: 0 }; - world.whitebox_call( - &forwarder_legacy_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .whitebox(forwarder_legacy::contract_obj, |sc| { sc.nft_create_compact( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID.to_token_identifier(), managed_biguint!(1), original_attributes, ); - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(original_attributes), - ), - )); + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, original_attributes); let new_attributes = Color { r: 255, @@ -84,34 +59,21 @@ fn test_nft_update_attributes_and_send() { b: 255, }; - world.whitebox_call( - &forwarder_legacy_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID, 1, "1"), - |sc| { - sc.nft_update_attributes(managed_token_id!(NFT_TOKEN_ID), 1, new_attributes); - - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(new_attributes), - ), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .whitebox(forwarder_legacy::contract_obj, |sc| { + sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); + + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); + + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, new_attributes); } diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs index 1dbf3952f2..c861c561ef 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs @@ -1,17 +1,15 @@ use forwarder::fwd_nft::{Color, ForwarderNftModule}; use multiversx_sc_scenario::imports::*; -const USER_ADDRESS_EXPR: &str = "address:user"; -const FORWARDER_ADDRESS_EXPR: &str = "sc:forwarder"; -const FORWARDER_PATH_EXPR: &str = "mxsc:output/forwarder.mxsc.json"; - -const NFT_TOKEN_ID_EXPR: &str = "str:COOL-123456"; -const NFT_TOKEN_ID: &[u8] = b"COOL-123456"; +const USER_ADDRESS: TestAddress = TestAddress::new("user"); +const FORWARDER_ADDRESS: TestSCAddress = TestSCAddress::new("forwarder"); +const FORWARDER_PATH: MxscPath = MxscPath::new("output/forwarder.mxsc.json"); +const NFT_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("COOL-123456"); fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); - blockchain.register_contract(FORWARDER_PATH_EXPR, forwarder::ContractBuilder); + blockchain.register_contract(FORWARDER_PATH, forwarder::ContractBuilder); blockchain } @@ -19,56 +17,40 @@ fn world() -> ScenarioWorld { fn test_nft_update_attributes_and_send() { let mut world = world(); - let forwarder_code = world.code_expression(FORWARDER_PATH_EXPR); let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTUpdateAttributes".to_string(), ]; - world.set_state_step( - SetStateStep::new() - .put_account(USER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - FORWARDER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(forwarder_code) - .esdt_roles(NFT_TOKEN_ID_EXPR, roles), - ), - ); - - let forwarder_whitebox = WhiteboxContract::new(FORWARDER_ADDRESS_EXPR, forwarder::contract_obj); + world.account(USER_ADDRESS).nonce(1); + world + .account(FORWARDER_ADDRESS) + .nonce(1) + .code(FORWARDER_PATH) + .esdt_roles(NFT_TOKEN_ID, roles); let original_attributes = Color { r: 0, g: 0, b: 0 }; - world.whitebox_call( - &forwarder_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR), - |sc| { + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .whitebox(forwarder::contract_obj, |sc| { sc.nft_create_compact( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID.to_token_identifier(), managed_biguint!(1), original_attributes, ); - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(original_attributes), - ), - )); + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, original_attributes); let new_attributes = Color { r: 255, @@ -76,34 +58,21 @@ fn test_nft_update_attributes_and_send() { b: 255, }; - world.whitebox_call( - &forwarder_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .esdt_transfer(NFT_TOKEN_ID, 1, "1"), - |sc| { - sc.nft_update_attributes(managed_token_id!(NFT_TOKEN_ID), 1, new_attributes); - - sc.send().direct_esdt( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(NFT_TOKEN_ID), - 1, - &managed_biguint!(1), - ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - NFT_TOKEN_ID_EXPR, - 1, - "1", - Some(new_attributes), - ), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + world + .tx() + .from(USER_ADDRESS) + .to(FORWARDER_ADDRESS) + .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .whitebox(forwarder::contract_obj, |sc| { + sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); + + sc.tx() + .to(USER_ADDRESS) + .esdt((NFT_TOKEN_ID.to_token_identifier(), 1, 1u32.into())) + .transfer(); + }); + + world + .check_account(USER_ADDRESS) + .esdt_nft_balance_and_attributes(NFT_TOKEN_ID, 1, 1, new_attributes); } diff --git a/framework/base/src/types/interaction/expr/test_token_identifier.rs b/framework/base/src/types/interaction/expr/test_token_identifier.rs index 47568b37ba..56d9a8bcd9 100644 --- a/framework/base/src/types/interaction/expr/test_token_identifier.rs +++ b/framework/base/src/types/interaction/expr/test_token_identifier.rs @@ -26,6 +26,10 @@ impl<'a> TestTokenIdentifier<'a> { pub fn eval_to_expr(&self) -> alloc::string::String { alloc::format!("{STR_PREFIX}{}", self.name) } + + pub fn to_token_identifier(&self) -> TokenIdentifier { + self.name.into() + } } impl<'a, Env> AnnotatedValue> for TestTokenIdentifier<'a> From ed3af84375d436f5d320a05793257eca4daadb8e Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 07:24:17 +0300 Subject: [PATCH 32/52] rewards distribution test migration --- .../rewards_distribution_integration_test.rs | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs b/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs index be3a4cb788..f9b64545bd 100644 --- a/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs +++ b/contracts/examples/rewards-distribution/tests/rewards_distribution_integration_test.rs @@ -6,7 +6,7 @@ use multiversx_sc_scenario::imports::*; use std::iter::zip; use rewards_distribution::{ - rewards_distribution_proxy, ContractObj, RewardsDistribution, DIVISION_SAFETY_CONSTANT, + rewards_distribution_proxy, RewardsDistribution, DIVISION_SAFETY_CONSTANT, }; const ALICE_ADDRESS: TestAddress = TestAddress::new("alice"); @@ -31,7 +31,6 @@ fn world() -> ScenarioWorld { struct RewardsDistributionTestState { world: ScenarioWorld, - rewards_distribution_whitebox: WhiteboxContract>, } impl RewardsDistributionTestState { @@ -40,15 +39,7 @@ impl RewardsDistributionTestState { world.account(OWNER_ADDRESS).nonce(1); - let rewards_distribution_whitebox = WhiteboxContract::new( - REWARDS_DISTRIBUTION_ADDRESS, - rewards_distribution::contract_obj, - ); - - Self { - world, - rewards_distribution_whitebox, - } + Self { world } } fn deploy_seed_nft_minter_contract(&mut self) -> &mut Self { @@ -110,10 +101,12 @@ fn test_compute_brackets() { .owner(OWNER_ADDRESS) .code(REWARDS_DISTRIBUTION_PATH); - state.world.whitebox_call( - &state.rewards_distribution_whitebox, - ScCallStep::new().from(OWNER_ADDRESS), - |sc| { + state + .world + .tx() + .from(OWNER_ADDRESS) + .to(REWARDS_DISTRIBUTION_ADDRESS) + .whitebox(rewards_distribution::contract_obj, |sc| { let brackets = utils::to_brackets(&[ (10, 2_000), (90, 6_000), @@ -140,8 +133,7 @@ fn test_compute_brackets() { assert_eq!(computed.end_index, expected_end_index); assert_eq!(computed.nft_reward_percent, expected_reward_percent); } - }, - ); + }); } #[test] From 6e2d67345fdba2bafb84790403d4dd6e0514e6b5 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 07:24:31 +0300 Subject: [PATCH 33/52] allow deprecated --- .../use-module/tests/token_merge_module_whitebox_test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index 803992d49b..5cc2180d01 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -1,3 +1,5 @@ +#![allow(deprecated)] // TODO: migrate to unified syntax at some point + use multiversx_sc_scenario::imports::*; use multiversx_sc_modules::token_merge::{ From f9c8de7b6d373e544ed87257f91f4515a5ab5769 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 24 Aug 2024 08:17:54 +0300 Subject: [PATCH 34/52] TestTokenIdentifier --- .../tests/forwarder_whitebox_legacy_test.rs | 2 +- .../tests/forwarder_whitebox_test.rs | 2 +- .../tests/transfer_role_whitebox_test.rs | 24 +--- .../tests/gov_module_whitebox_test.rs | 117 +++++------------- .../tests/staking_module_whitebox_test.rs | 70 ++++------- .../interaction/expr/test_token_identifier.rs | 8 ++ .../base/src/types/interaction/tx_payment.rs | 2 + .../tx_payment/test_esdt_transfer.rs | 69 +++++++++++ 8 files changed, 137 insertions(+), 157 deletions(-) create mode 100644 framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs index f6cfb158f6..88e945529a 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs @@ -63,7 +63,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) .whitebox(forwarder_legacy::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs index c861c561ef..b33b7d98a8 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs @@ -62,7 +62,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .single_esdt(&TokenIdentifier::from(NFT_TOKEN_ID), 1, &1u32.into()) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) .whitebox(forwarder::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); diff --git a/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs b/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs index 130c2b237c..5ed03c38bc 100644 --- a/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs +++ b/contracts/feature-tests/composability/transfer-role-features/tests/transfer_role_whitebox_test.rs @@ -70,11 +70,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( managed_token_id!(TRANSFER_TOKEN_ID_EXPR), @@ -101,11 +97,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .returns(ExpectError(4u64, "Destination address not whitelisted")) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( @@ -126,11 +118,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( managed_token_id!(TRANSFER_TOKEN_ID_EXPR), @@ -159,11 +147,7 @@ fn test_transfer_role() { .tx() .from(USER_ADDRESS) .to(TRANSFER_ROLE_FEATURES_ADDRESS) - .single_esdt( - &TokenIdentifier::from(TRANSFER_TOKEN_ID), - 0, - &BigUint::from(100u64), - ) + .payment(TestEsdtTransfer(TRANSFER_TOKEN_ID, 0, 100)) .whitebox(transfer_role_features::contract_obj, |sc| { let payments = ManagedVec::from_single_item(EsdtTokenPayment::new( managed_token_id!(TRANSFER_TOKEN_ID_EXPR), diff --git a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs index 288d3042f5..800797024b 100644 --- a/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/gov_module_whitebox_test.rs @@ -4,8 +4,7 @@ use multiversx_sc_modules::governance::{ }; use multiversx_sc_scenario::imports::*; -const GOV_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("GOV-123456"); -const GOV_TOKEN_ID: &[u8] = b"GOV-123456"; +const GOV_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("GOV-123456"); const QUORUM: u64 = 1_500; const MIN_BALANCE_PROPOSAL: u64 = 500; const VOTING_DELAY_BLOCKS: u64 = 10; @@ -42,19 +41,19 @@ fn setup() -> ScenarioWorld { world .account(OWNER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); world .account(FIRST_USER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); world .account(SECOND_USER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); world .account(THIRD_USER_ADDRESS) .nonce(1) - .esdt_balance(GOV_TOKEN_ID_EXPR, INITIAL_GOV_TOKEN_BALANCE); + .esdt_balance(GOV_TOKEN_ID, INITIAL_GOV_TOKEN_BALANCE); // init let new_address = world @@ -66,7 +65,7 @@ fn setup() -> ScenarioWorld { .returns(ReturnsNewBech32Address) .whitebox(use_module::contract_obj, |sc| { sc.init_governance_module( - TokenIdentifier::from(GOV_TOKEN_ID_EXPR), + TokenIdentifier::from(GOV_TOKEN_ID), BigUint::from(QUORUM), BigUint::from(MIN_BALANCE_PROPOSAL), VOTING_DELAY_BLOCKS, @@ -96,11 +95,7 @@ pub fn propose( .tx() .from(proposer) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID_EXPR), - 0, - &BigUint::from(gov_token_amount), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, gov_token_amount)) .whitebox(use_module::contract_obj, |sc| { let mut args_managed = ManagedVec::new(); for arg in args { @@ -151,11 +146,7 @@ fn test_change_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(999u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 999)) .returns(ExpectError(4u64, "Proposal is not active")) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); @@ -168,11 +159,7 @@ fn test_change_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(999u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 999)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -218,11 +205,7 @@ fn test_change_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -232,11 +215,7 @@ fn test_change_gov_config() { .tx() .from(OWNER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); }); @@ -262,11 +241,7 @@ fn test_change_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .returns(ExpectError(4u64, "Already voted for this proposal")) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); @@ -277,11 +252,7 @@ fn test_change_gov_config() { .tx() .from(THIRD_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -330,16 +301,16 @@ fn test_change_gov_config() { world .check_account(FIRST_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(300u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(300u64)); world .check_account(SECOND_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(1u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(1u64)); world .check_account(THIRD_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); world .check_account(OWNER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); } #[test] @@ -366,11 +337,7 @@ fn test_down_veto_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(300u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 300)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -382,11 +349,7 @@ fn test_down_veto_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -395,11 +358,7 @@ fn test_down_veto_gov_config() { .tx() .from(THIRD_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(200u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 200)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVetoVote) }); @@ -419,15 +378,15 @@ fn test_down_veto_gov_config() { world .check_account(FIRST_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(200u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(200u64)); world .check_account(SECOND_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); world .check_account(THIRD_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(800u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(800u64)); } #[test] @@ -454,11 +413,7 @@ fn test_abstain_vote_gov_config() { .tx() .from(FIRST_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(500u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 500)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::UpVote); }); @@ -470,11 +425,7 @@ fn test_abstain_vote_gov_config() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(400u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 400)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote); }); @@ -483,11 +434,7 @@ fn test_abstain_vote_gov_config() { .tx() .from(THIRD_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(600u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 600)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::AbstainVote); }); @@ -527,13 +474,13 @@ fn test_abstain_vote_gov_config() { world .check_account(FIRST_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::zero()); + .esdt_balance(GOV_TOKEN_ID, BigUint::zero()); world .check_account(SECOND_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(600u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(600u64)); world .check_account(THIRD_USER_ADDRESS) - .esdt_balance(GOV_TOKEN_ID_EXPR, BigUint::from(400u64)); + .esdt_balance(GOV_TOKEN_ID, BigUint::from(400u64)); } #[test] @@ -560,11 +507,7 @@ fn test_gov_cancel_defeated_proposal() { .tx() .from(SECOND_USER_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(GOV_TOKEN_ID), - 0, - &BigUint::from(999u64), - ) + .payment(TestEsdtTransfer(GOV_TOKEN_ID, 0, 999)) .whitebox(use_module::contract_obj, |sc| { sc.vote(proposal_id, VoteType::DownVote) }); diff --git a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs index 0f705ad131..643387b634 100644 --- a/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/staking_module_whitebox_test.rs @@ -1,8 +1,7 @@ use multiversx_sc_modules::staking::StakingModule; use multiversx_sc_scenario::imports::*; -const STAKING_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("STAKE-123456"); -const STAKING_TOKEN_ID: &[u8] = b"STAKE-123456"; +const STAKING_TOKEN_ID: TestTokenIdentifier = TestTokenIdentifier::new("STAKE-123456"); const INITIAL_BALANCE: u64 = 2_000_000; const REQUIRED_STAKE_AMOUNT: u64 = 1_000_000; const SLASH_AMOUNT: u64 = 600_000; @@ -34,27 +33,27 @@ fn test_staking_module() { world .account(ALICE_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(BOB_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(CAROL_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(EVE_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(PAUL_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); world .account(SALLY_ADDRESS) .nonce(1) - .esdt_balance(STAKING_TOKEN_ID_EXPR, INITIAL_BALANCE); + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE); // init let new_address = world @@ -73,7 +72,7 @@ fn test_staking_module() { whitelist.push(SALLY_ADDRESS.to_managed_address()); sc.init_staking_module( - &EgldOrEsdtTokenIdentifier::esdt(STAKING_TOKEN_ID), + &EgldOrEsdtTokenIdentifier::esdt(STAKING_TOKEN_ID.to_token_identifier()), &BigUint::from(REQUIRED_STAKE_AMOUNT), &BigUint::from(SLASH_AMOUNT), QUORUM, @@ -88,11 +87,7 @@ fn test_staking_module() { .tx() .from(EVE_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .returns(ExpectError(4u64, "Only whitelisted members can stake")) .whitebox(use_module::contract_obj, |sc| { sc.stake(); @@ -103,11 +98,11 @@ fn test_staking_module() { .tx() .from(ALICE_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), + .payment(TestEsdtTransfer( + STAKING_TOKEN_ID, 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT / 2), - ) + REQUIRED_STAKE_AMOUNT / 2, + )) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -126,11 +121,7 @@ fn test_staking_module() { .tx() .from(BOB_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -139,11 +130,7 @@ fn test_staking_module() { .tx() .from(CAROL_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -152,11 +139,7 @@ fn test_staking_module() { .tx() .from(PAUL_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -165,11 +148,7 @@ fn test_staking_module() { .tx() .from(SALLY_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); }); @@ -199,11 +178,7 @@ fn test_staking_module() { .tx() .from(ALICE_ADDRESS) .to(USE_MODULE_ADDRESS) - .single_esdt( - &TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), - 0, - &BigUint::from(REQUIRED_STAKE_AMOUNT), - ) + .payment(TestEsdtTransfer(STAKING_TOKEN_ID, 0, REQUIRED_STAKE_AMOUNT)) .whitebox(use_module::contract_obj, |sc| { sc.stake(); let alice_staked_amount = sc.staked_amount(&ALICE_ADDRESS.to_managed_address()).get(); @@ -222,7 +197,7 @@ fn test_staking_module() { world .check_account(ALICE_ADDRESS) - .esdt_balance(STAKING_TOKEN_ID_EXPR, BigUint::from(1_000_000u64)); + .esdt_balance(STAKING_TOKEN_ID, BigUint::from(1_000_000u64)); // alice vote to slash bob @@ -386,8 +361,7 @@ fn test_staking_module() { sc.unstake(BigUint::from(400_000u64)); }); - world.check_account(ALICE_ADDRESS).esdt_balance( - TokenIdentifier::from(STAKING_TOKEN_ID_EXPR), - BigUint::from(INITIAL_BALANCE - SLASH_AMOUNT), - ); + world + .check_account(ALICE_ADDRESS) + .esdt_balance(STAKING_TOKEN_ID, INITIAL_BALANCE - SLASH_AMOUNT); } diff --git a/framework/base/src/types/interaction/expr/test_token_identifier.rs b/framework/base/src/types/interaction/expr/test_token_identifier.rs index 56d9a8bcd9..68865d8fbc 100644 --- a/framework/base/src/types/interaction/expr/test_token_identifier.rs +++ b/framework/base/src/types/interaction/expr/test_token_identifier.rs @@ -30,6 +30,14 @@ impl<'a> TestTokenIdentifier<'a> { pub fn to_token_identifier(&self) -> TokenIdentifier { self.name.into() } + + pub fn as_str(&self) -> &str { + self.name + } + + pub fn as_bytes(&self) -> &[u8] { + self.name.as_bytes() + } } impl<'a, Env> AnnotatedValue> for TestTokenIdentifier<'a> diff --git a/framework/base/src/types/interaction/tx_payment.rs b/framework/base/src/types/interaction/tx_payment.rs index c5bcc10637..bed41cc775 100644 --- a/framework/base/src/types/interaction/tx_payment.rs +++ b/framework/base/src/types/interaction/tx_payment.rs @@ -1,3 +1,4 @@ +mod test_esdt_transfer; mod tx_payment_egld; mod tx_payment_egld_or_esdt; mod tx_payment_egld_or_esdt_refs; @@ -11,6 +12,7 @@ mod tx_payment_single_esdt; mod tx_payment_single_esdt_ref; mod tx_payment_single_esdt_triple; +pub use test_esdt_transfer::TestEsdtTransfer; pub use tx_payment_egld::{Egld, EgldPayment}; pub use tx_payment_egld_value::TxEgldValue; pub use tx_payment_multi_esdt::TxPaymentMultiEsdt; diff --git a/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs b/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs new file mode 100644 index 0000000000..99d00a219e --- /dev/null +++ b/framework/base/src/types/interaction/tx_payment/test_esdt_transfer.rs @@ -0,0 +1,69 @@ +use crate::{ + api::ManagedTypeApi, + types::{ + BigUint, EsdtTokenPayment, FullPaymentData, FunctionCall, ManagedAddress, + TestTokenIdentifier, TxEnv, TxFrom, TxPayment, TxToSpecified, + }, +}; + +/// Syntactic sugar for quickly writing ESDT transfers in tests. +/// +/// The fields are: +/// 1. token identifier, as TestTokenIdentifier +/// 2. nonce +/// 3. amount +/// +/// The amount is represented as u64, since for most tests it is enough. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct TestEsdtTransfer<'a>(pub TestTokenIdentifier<'a>, pub u64, pub u64); + +impl<'a, Api> From> for EsdtTokenPayment +where + Api: ManagedTypeApi, +{ + fn from(value: TestEsdtTransfer<'a>) -> Self { + EsdtTokenPayment::new(value.0.to_token_identifier(), value.1, value.2.into()) + } +} + +impl<'a, Env> TxPayment for TestEsdtTransfer<'a> +where + Env: TxEnv, +{ + #[inline] + fn is_no_payment(&self, _env: &Env) -> bool { + self.2 == 0 + } + + #[inline] + fn perform_transfer_execute( + self, + env: &Env, + to: &ManagedAddress, + gas_limit: u64, + fc: FunctionCall, + ) { + EsdtTokenPayment::from(self).perform_transfer_execute(env, to, gas_limit, fc); + } + + #[inline] + fn with_normalized( + self, + env: &Env, + from: &From, + to: To, + fc: FunctionCall, + f: F, + ) -> R + where + From: TxFrom, + To: TxToSpecified, + F: FnOnce(&ManagedAddress, &BigUint, FunctionCall) -> R, + { + EsdtTokenPayment::from(self).with_normalized(env, from, to, fc, f) + } + + fn into_full_payment_data(self, env: &Env) -> FullPaymentData { + EsdtTokenPayment::from(self).into_full_payment_data(env) + } +} From 266b717dccf2f27bb311e3b53d740ba63bc866a6 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 08:42:54 +0300 Subject: [PATCH 35/52] test fix --- .../composability/tests/forwarder_whitebox_legacy_test.rs | 2 +- .../composability/tests/forwarder_whitebox_test.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs index 88e945529a..424c1508a4 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_legacy_test.rs @@ -63,7 +63,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 1, 1)) .whitebox(forwarder_legacy::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); diff --git a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs index b33b7d98a8..c6f2b54a78 100644 --- a/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs +++ b/contracts/feature-tests/composability/tests/forwarder_whitebox_test.rs @@ -62,7 +62,7 @@ fn test_nft_update_attributes_and_send() { .tx() .from(USER_ADDRESS) .to(FORWARDER_ADDRESS) - .payment(TestEsdtTransfer(NFT_TOKEN_ID, 0, 1)) + .payment(TestEsdtTransfer(NFT_TOKEN_ID, 1, 1)) .whitebox(forwarder::contract_obj, |sc| { sc.nft_update_attributes(NFT_TOKEN_ID.to_token_identifier(), 1, new_attributes); From e21a5aea170f844b2f12ea2fa4f82f2a49735721 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 08:46:12 +0300 Subject: [PATCH 36/52] clippy fix --- contracts/examples/nft-minter/src/nft_module.rs | 2 +- .../composability/forwarder-legacy/src/fwd_esdt_legacy.rs | 3 +-- .../feature-tests/composability/forwarder/src/fwd_esdt.rs | 3 +-- .../feature-tests/composability/local-esdt-and-nft/src/lib.rs | 3 +-- .../feature-tests/erc-style-contracts/erc1155/src/erc1155.rs | 4 ++-- .../feature-tests/rust-testing-framework-tester/src/lib.rs | 2 +- framework/base/src/types/managed/wrapped/managed_vec_item.rs | 1 + 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/contracts/examples/nft-minter/src/nft_module.rs b/contracts/examples/nft-minter/src/nft_module.rs index da97c0d171..66f50ea958 100644 --- a/contracts/examples/nft-minter/src/nft_module.rs +++ b/contracts/examples/nft-minter/src/nft_module.rs @@ -123,7 +123,7 @@ pub trait NftModule { ) { match result { ManagedAsyncCallResult::Ok(token_id) => { - self.nft_token_id().set(&token_id.unwrap_esdt()); + self.nft_token_id().set(token_id.unwrap_esdt()); }, ManagedAsyncCallResult::Err(_) => { let returned = self.call_value().egld_or_single_esdt(); diff --git a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs index b56db69bb8..6fa20793d8 100644 --- a/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs +++ b/contracts/feature-tests/composability/forwarder-legacy/src/fwd_esdt_legacy.rs @@ -128,8 +128,7 @@ pub trait ForwarderEsdtModule: fwd_storage_legacy::ForwarderStorageModule { // so we can get the token identifier and amount from the call data match result { ManagedAsyncCallResult::Ok(()) => { - self.last_issued_token() - .set(&token_identifier.unwrap_esdt()); + self.last_issued_token().set(token_identifier.unwrap_esdt()); self.last_error_message().clear(); }, ManagedAsyncCallResult::Err(message) => { diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs b/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs index fcc3912ecc..a4dbaa28b1 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_esdt.rs @@ -132,8 +132,7 @@ pub trait ForwarderEsdtModule: fwd_storage::ForwarderStorageModule { // so we can get the token identifier and amount from the call data match result { ManagedAsyncCallResult::Ok(()) => { - self.last_issued_token() - .set(&token_identifier.unwrap_esdt()); + self.last_issued_token().set(token_identifier.unwrap_esdt()); self.last_error_message().clear(); }, ManagedAsyncCallResult::Err(message) => { diff --git a/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs b/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs index 55f0577795..0291d36131 100644 --- a/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs +++ b/contracts/feature-tests/composability/local-esdt-and-nft/src/lib.rs @@ -276,8 +276,7 @@ pub trait LocalEsdtAndEsdtNft { // so we can get the token identifier and amount from the call data match result { ManagedAsyncCallResult::Ok(()) => { - self.last_issued_token() - .set(&token_identifier.unwrap_esdt()); + self.last_issued_token().set(token_identifier.unwrap_esdt()); self.last_error_message().clear(); }, ManagedAsyncCallResult::Err(message) => { diff --git a/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs b/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs index 725cff90de..b4d8acc941 100644 --- a/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs +++ b/contracts/feature-tests/erc-style-contracts/erc1155/src/erc1155.rs @@ -160,7 +160,7 @@ pub trait Erc1155 { self.token_owner(type_id, nft_id).set(to); } else { self.token_owner(type_id, nft_id) - .set(&ManagedAddress::zero()); + .set(ManagedAddress::zero()); } } @@ -320,7 +320,7 @@ pub trait Erc1155 { let amount = BigUint::from(1u32); self.decrease_balance(owner, type_id, &amount); self.token_owner(type_id, nft_id) - .set(&ManagedAddress::zero()); + .set(ManagedAddress::zero()); } /// Range is inclusive for both `start` and `end` diff --git a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs index ad3766e123..ffc411dad0 100644 --- a/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs +++ b/contracts/feature-tests/rust-testing-framework-tester/src/lib.rs @@ -21,7 +21,7 @@ pub struct StructWithManagedTypes { pub trait RustTestingFrameworkTester: dummy_module::DummyModule { #[init] fn init(&self) -> ManagedBuffer { - self.total_value().set(&BigUint::from(1u32)); + self.total_value().set(BigUint::from(1u32)); b"constructor-result".into() } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 648635e143..9f21a13de4 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -31,6 +31,7 @@ pub trait ManagedVecItem: 'static { /// - For items with Copy semantics, it should be the type itself. /// - For managed types, ManagedRef does the job. /// - For any other types, `Self` is currently used, although this is technically unsafe. + /// /// TODO: wrap other types in readonly wrapper. type Ref<'a>: Borrow; From 112120f1dbc39b182ecbcff268df80ef571a4746 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 14:48:02 +0300 Subject: [PATCH 37/52] ed25519-dalek reverted downgrade --- Cargo.lock | 520 +++++++++++++++++++------------------ vm/Cargo.toml | 2 +- vm/src/crypto_functions.rs | 27 +- 3 files changed, 281 insertions(+), 268 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fecbf652fe..afd520f5eb 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aes" version = "0.8.4" @@ -201,7 +207,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -296,8 +302,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", - "rand_core 0.6.4", + "rand", + "rand_core", "serde", "unicode-normalization", ] @@ -308,27 +314,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -395,15 +386,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.7" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -458,9 +452,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.11" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -468,9 +462,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.11" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -480,9 +474,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -536,6 +530,12 @@ dependencies = [ "vault", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "convert_case" version = "0.6.0" @@ -566,15 +566,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -702,22 +702,25 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.0" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", "subtle", "zeroize", ] [[package]] -name = "derive_arbitrary" -version = "1.3.2" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", @@ -725,12 +728,24 @@ dependencies = [ ] [[package]] -name = "digest" -version = "0.9.0" +name = "der" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "generic-array", + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -739,7 +754,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] @@ -773,24 +788,25 @@ dependencies = [ [[package]] name = "ed25519" -version = "1.5.3" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ + "pkcs8", "signature", ] [[package]] name = "ed25519-dalek" -version = "1.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "rand 0.7.3", "serde", - "sha2 0.9.9", + "sha2", + "subtle", "zeroize", ] @@ -1037,9 +1053,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "first-contract" @@ -1060,12 +1082,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1296,17 +1318,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -1316,7 +1327,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1341,9 +1352,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -1398,7 +1409,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -1502,9 +1513,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", @@ -1548,9 +1559,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown", @@ -1606,9 +1617,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1709,9 +1720,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linked-list-repeat" @@ -1862,15 +1873,24 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.52.0", ] @@ -1944,7 +1964,7 @@ dependencies = [ name = "multiversx-chain-vm" version = "0.9.0" dependencies = [ - "bitflags 2.6.0", + "bitflags", "colored", "ed25519-dalek", "hex", @@ -1953,9 +1973,9 @@ dependencies = [ "multiversx-chain-vm-executor", "num-bigint", "num-traits", - "rand 0.8.5", + "rand", "rand_seeder", - "sha2 0.10.8", + "sha2", "sha3", ] @@ -1970,11 +1990,11 @@ name = "multiversx-price-aggregator-sc" version = "0.52.3" dependencies = [ "arrayvec", - "getrandom 0.2.15", + "getrandom", "multiversx-sc", "multiversx-sc-modules", "multiversx-sc-scenario", - "rand 0.8.5", + "rand", ] [[package]] @@ -1990,7 +2010,7 @@ dependencies = [ name = "multiversx-sc" version = "0.52.3" dependencies = [ - "bitflags 2.6.0", + "bitflags", "hex-literal", "multiversx-sc-codec", "multiversx-sc-derive", @@ -2099,7 +2119,7 @@ dependencies = [ "pathdiff", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "unwrap-infallible", ] @@ -2142,13 +2162,13 @@ dependencies = [ "log", "pbkdf2", "pem", - "rand 0.8.5", + "rand", "reqwest", "scrypt", "serde", "serde_json", "serde_repr", - "sha2 0.10.8", + "sha2", "sha3", "tokio", "uuid", @@ -2289,9 +2309,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -2302,19 +2322,13 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "openssl" version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -2439,7 +2453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -2475,7 +2489,7 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.7", + "digest", "hmac", ] @@ -2543,6 +2557,16 @@ dependencies = [ "ping-pong-egld", ] +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -2551,12 +2575,11 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "ppv-lite86" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2288c0e17cc8d342c712bb43a257a80ebffce59cdb33d5000d8348f3ec02528b" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ "zerocopy", - "zerocopy-derive", ] [[package]] @@ -2669,19 +2692,6 @@ dependencies = [ "nibble_vec", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -2689,18 +2699,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2710,16 +2710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2728,16 +2719,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2746,7 +2728,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -2779,14 +2761,14 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -2813,9 +2795,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64", "bytes", @@ -2852,7 +2834,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -2880,7 +2862,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom", "libc", "spin", "untrusted", @@ -2961,7 +2943,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2983,9 +2965,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ "base64", "rustls-pki-types", @@ -2993,9 +2975,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -3072,7 +3054,7 @@ dependencies = [ "password-hash", "pbkdf2", "salsa20", - "sha2 0.10.8", + "sha2", ] [[package]] @@ -3098,7 +3080,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -3156,18 +3138,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -3176,9 +3158,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "indexmap", "itoa", @@ -3236,19 +3218,6 @@ dependencies = [ "set-repeat", ] -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.8" @@ -3257,7 +3226,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -3266,10 +3235,16 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -3281,9 +3256,12 @@ dependencies = [ [[package]] name = "signature" -version = "1.6.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] [[package]] name = "simd-adler32" @@ -3339,6 +3317,16 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "str-repeat" version = "0.0.0" @@ -3383,23 +3371,26 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -3407,14 +3398,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3479,9 +3471,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", @@ -3542,9 +3534,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "indexmap", "serde", @@ -3564,9 +3556,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.18" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "serde", @@ -3592,15 +3584,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -3731,7 +3723,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ - "getrandom 0.2.15", + "getrandom", ] [[package]] @@ -3798,12 +3790,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3812,19 +3798,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -3837,9 +3824,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -3849,9 +3836,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3859,9 +3846,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -3872,9 +3859,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasmparser" @@ -3883,7 +3870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6" dependencies = [ "ahash", - "bitflags 2.6.0", + "bitflags", "hashbrown", "indexmap", "semver", @@ -3903,9 +3890,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -3913,11 +3900,41 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -3938,6 +3955,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -4061,23 +4087,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.16" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "zerocopy" version = "0.7.35" @@ -4104,26 +4120,12 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "zip" -version = "2.1.5" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b895748a3ebcb69b9d38dcfdf21760859a4b0d0b0015277640c2ef4c69640e6f" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "crc32fast", diff --git a/vm/Cargo.toml b/vm/Cargo.toml index baf8ec3894..31bb9afcdf 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -32,7 +32,7 @@ bitflags = "=2.6.0" colored = "2.1.0" rand = { version= "0.8.5", optional = true } rand_seeder = { version= "0.2.2", optional = true } -ed25519-dalek = { version = "1.0.1" , optional = true } +ed25519-dalek = { version = "2.1.0" , optional = true } [dependencies.multiversx-chain-vm-executor] version = "0.2.0" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index 9d61e9ccc9..fed81f654a 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -18,19 +18,30 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { #[cfg(feature = "wasm-incopatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { - use ed25519_dalek::*; + use ed25519_dalek::{Signature, VerifyingKey, Verifier}; - let public = PublicKey::from_bytes(key); - if public.is_err() { + let key_32: [u8; 32] = if let Ok(key_32) = key.try_into() { + key_32 + } else { return false; - } + }; + let signature_64: [u8; 64] = if let Ok(signature_64) = signature.try_into() { + signature_64 + } else { + return false; + }; - let sig = Signature::from_bytes(signature); - if sig.is_err() { + let verifying_key_result = VerifyingKey::from_bytes(&key_32); + let verifying_key = if let Ok(verifying_key) = verifying_key_result { + verifying_key + } else { return false; - } + }; + + let sig = Signature::from_bytes(&signature_64); - public.unwrap().verify(message, &sig.unwrap()).is_ok() + let result = verifying_key.verify(message, &sig); + result.is_ok() } #[cfg(not(feature = "wasm-incopatible"))] From 2a1327911f10710f6c9ed22a3a44e5e0ef67af03 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 14:49:07 +0300 Subject: [PATCH 38/52] wasm-incompatible feature typo --- framework/scenario/Cargo.toml | 4 ++-- vm/Cargo.toml | 2 +- vm/src/crypto_functions.rs | 6 +++--- vm/src/tx_mock.rs | 8 ++++---- vm/src/tx_mock/blockchain_rng_unsupported.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/framework/scenario/Cargo.toml b/framework/scenario/Cargo.toml index 9cf7f2a553..0e13cb71dd 100644 --- a/framework/scenario/Cargo.toml +++ b/framework/scenario/Cargo.toml @@ -32,8 +32,8 @@ colored = "2.0" unwrap-infallible = "0.1.5" [features] -default = ["wasm-incopatible"] -wasm-incopatible = ["multiversx-chain-vm/wasm-incopatible"] +default = ["wasm-incompatible"] +wasm-incompatible = ["multiversx-chain-vm/wasm-incompatible"] run-go-tests = [] [dependencies.multiversx-sc] diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 31bb9afcdf..568c7e512c 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -18,7 +18,7 @@ categories = ["cryptography::cryptocurrencies", "development-tools::debugging"] [features] # not supported when compiling to wasm -wasm-incopatible = ["rand", "rand_seeder", "ed25519-dalek"] +wasm-incompatible = ["rand", "rand_seeder", "ed25519-dalek"] [dependencies] num-bigint = "0.4" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index fed81f654a..a1277ceac5 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -16,7 +16,7 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { hasher.finalize().into() } -#[cfg(feature = "wasm-incopatible")] +#[cfg(feature = "wasm-incompatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { use ed25519_dalek::{Signature, VerifyingKey, Verifier}; @@ -44,7 +44,7 @@ pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { result.is_ok() } -#[cfg(not(feature = "wasm-incopatible"))] +#[cfg(not(feature = "wasm-incompatible"))] pub fn verify_ed25519(_key: &[u8], _message: &[u8], _signature: &[u8]) -> bool { - panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incopatible` needs to be enabled") + panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incompatible` needs to be enabled") } diff --git a/vm/src/tx_mock.rs b/vm/src/tx_mock.rs index bd508d569e..ce63ddfe7a 100644 --- a/vm/src/tx_mock.rs +++ b/vm/src/tx_mock.rs @@ -37,12 +37,12 @@ pub use tx_panic::*; pub use tx_result::*; pub use tx_result_calls::*; -#[cfg(feature = "wasm-incopatible")] +#[cfg(feature = "wasm-incompatible")] mod blockchain_rng; -#[cfg(feature = "wasm-incopatible")] +#[cfg(feature = "wasm-incompatible")] pub use blockchain_rng::BlockchainRng; -#[cfg(not(feature = "wasm-incopatible"))] +#[cfg(not(feature = "wasm-incompatible"))] mod blockchain_rng_unsupported; -#[cfg(not(feature = "wasm-incopatible"))] +#[cfg(not(feature = "wasm-incompatible"))] pub use blockchain_rng_unsupported::BlockchainRng; diff --git a/vm/src/tx_mock/blockchain_rng_unsupported.rs b/vm/src/tx_mock/blockchain_rng_unsupported.rs index 698be4ac11..6339cbaffc 100644 --- a/vm/src/tx_mock/blockchain_rng_unsupported.rs +++ b/vm/src/tx_mock/blockchain_rng_unsupported.rs @@ -9,6 +9,6 @@ impl BlockchainRng { } pub fn next_bytes(&mut self, _length: usize) -> Vec { - panic!("BlockchainRng not supported for wasm builds, feature `wasm-incopatible` needs to be enabled") + panic!("BlockchainRng not supported for wasm builds, feature `wasm-incompatible` needs to be enabled") } } From 12d3da51879b2cdf88aeea15e1ffc906c94d633c Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 14:53:54 +0300 Subject: [PATCH 39/52] dependency upgrade --- Cargo.lock | 24 ++++++++++++------------ data/codec-derive/Cargo.toml | 4 ++-- data/codec/Cargo.toml | 2 +- framework/derive/Cargo.toml | 4 ++-- framework/meta-lib/Cargo.toml | 4 ++-- vm/Cargo.toml | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afd520f5eb..b7fe71048c 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "atomic-waker" @@ -2675,9 +2675,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2724,9 +2724,9 @@ dependencies = [ [[package]] name = "rand_seeder" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2890aaef0aa82719a50e808de264f9484b74b442e1a3a0e5ee38243ac40bdb" +checksum = "4a9febe641d2842ffc76ee962668a17578767c4e01735e4802b21ed9a24b2e4e" dependencies = [ "rand_core", ] @@ -3357,9 +3357,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", @@ -3865,9 +3865,9 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasmparser" -version = "0.214.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6" +checksum = "bcdee6bea3619d311fb4b299721e89a986c3470f804b6d534340e412589028e3" dependencies = [ "ahash", "bitflags", @@ -3879,9 +3879,9 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.214.0" +version = "0.216.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d4f2b3f7bd2ba10f99e03f885ff90d5db3455e163bccecebbbf60406bd8980" +checksum = "8f82916f3892e53620639217d6ec78fe15c678352a3fbf3f3745b6417d0bd70f" dependencies = [ "anyhow", "termcolor", diff --git a/data/codec-derive/Cargo.toml b/data/codec-derive/Cargo.toml index 934b041232..707de3c33a 100644 --- a/data/codec-derive/Cargo.toml +++ b/data/codec-derive/Cargo.toml @@ -22,6 +22,6 @@ default = ["syn/full", "syn/parsing", "syn/extra-traits"] [dependencies] proc-macro2 = "=1.0.86" -quote = "=1.0.36" -syn = "=2.0.72" +quote = "=1.0.37" +syn = "=2.0.76" hex = "=0.4.3" diff --git a/data/codec/Cargo.toml b/data/codec/Cargo.toml index b09697b84c..be2e7f39f4 100644 --- a/data/codec/Cargo.toml +++ b/data/codec/Cargo.toml @@ -22,7 +22,7 @@ version = "=0.20.1" optional = true [dependencies] -arrayvec = { version = "=0.7.4", default-features = false } +arrayvec = { version = "=0.7.6", default-features = false } num-bigint = { version = "0.4", optional = true } # can only be used in std contexts unwrap-infallible = "0.1.5" diff --git a/framework/derive/Cargo.toml b/framework/derive/Cargo.toml index 50f6ef6dd0..d4246c314b 100644 --- a/framework/derive/Cargo.toml +++ b/framework/derive/Cargo.toml @@ -15,8 +15,8 @@ categories = ["cryptography::cryptocurrencies", "development-tools::procedural-m [dependencies] proc-macro2 = "=1.0.86" -quote = "=1.0.36" -syn = "=2.0.72" +quote = "=1.0.37" +syn = "=2.0.76" hex = "=0.4.3" radix_trie = "=0.2.1" diff --git a/framework/meta-lib/Cargo.toml b/framework/meta-lib/Cargo.toml index f3149ee0c8..484e9034cb 100644 --- a/framework/meta-lib/Cargo.toml +++ b/framework/meta-lib/Cargo.toml @@ -26,8 +26,8 @@ colored = "2.0" lazy_static = "1.4.0" convert_case = "0.6.0" hex = "0.4" -wasmparser = "0.214" -wasmprinter = "0.214" +wasmparser = "0.216" +wasmprinter = "0.216" semver = "1.0.20" [dependencies.multiversx-sc] diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 568c7e512c..b823a5df66 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -31,7 +31,7 @@ hex-literal = "=0.4.1" bitflags = "=2.6.0" colored = "2.1.0" rand = { version= "0.8.5", optional = true } -rand_seeder = { version= "0.2.2", optional = true } +rand_seeder = { version= "0.3.0", optional = true } ed25519-dalek = { version = "2.1.0" , optional = true } [dependencies.multiversx-chain-vm-executor] From 259aaf2ee02f6fc5483ace28190473279d468e99 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 26 Aug 2024 15:13:45 +0300 Subject: [PATCH 40/52] rand_seeder & ed25519-dalek no longer wasm-incompatible --- vm/Cargo.toml | 6 +++--- vm/src/crypto_functions.rs | 8 +------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/vm/Cargo.toml b/vm/Cargo.toml index b823a5df66..7e5349688d 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -18,7 +18,7 @@ categories = ["cryptography::cryptocurrencies", "development-tools::debugging"] [features] # not supported when compiling to wasm -wasm-incompatible = ["rand", "rand_seeder", "ed25519-dalek"] +wasm-incompatible = ["rand"] [dependencies] num-bigint = "0.4" @@ -31,8 +31,8 @@ hex-literal = "=0.4.1" bitflags = "=2.6.0" colored = "2.1.0" rand = { version= "0.8.5", optional = true } -rand_seeder = { version= "0.3.0", optional = true } -ed25519-dalek = { version = "2.1.0" , optional = true } +rand_seeder = "0.3.0" +ed25519-dalek = "2.1.0" [dependencies.multiversx-chain-vm-executor] version = "0.2.0" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index a1277ceac5..3dae63aad7 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -16,9 +16,8 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { hasher.finalize().into() } -#[cfg(feature = "wasm-incompatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { - use ed25519_dalek::{Signature, VerifyingKey, Verifier}; + use ed25519_dalek::{Signature, Verifier, VerifyingKey}; let key_32: [u8; 32] = if let Ok(key_32) = key.try_into() { key_32 @@ -43,8 +42,3 @@ pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { let result = verifying_key.verify(message, &sig); result.is_ok() } - -#[cfg(not(feature = "wasm-incompatible"))] -pub fn verify_ed25519(_key: &[u8], _message: &[u8], _signature: &[u8]) -> bool { - panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incompatible` needs to be enabled") -} From 82cd85aa89ab08e087cb0d18e17151a2f3f6f782 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Mon, 26 Aug 2024 16:38:51 +0300 Subject: [PATCH 41/52] updated bech32 crate v0.11 --- Cargo.lock | 4 ++-- framework/scenario/Cargo.toml | 2 +- framework/scenario/src/bech32.rs | 9 ++++----- sdk/core/Cargo.toml | 2 +- sdk/core/src/crypto/public_key.rs | 5 +++-- sdk/core/src/data/address.rs | 8 ++++---- sdk/scenario-format/Cargo.toml | 2 +- sdk/scenario-format/src/value_interpreter/functions.rs | 5 ++--- tools/mxpy-snippet-generator/Cargo.toml | 2 +- tools/mxpy-snippet-generator/src/helper_types.rs | 4 +--- 10 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7fe71048c..ac352c58c6 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,9 +266,9 @@ dependencies = [ [[package]] name = "bech32" -version = "0.9.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" [[package]] name = "benchmark-common" diff --git a/framework/scenario/Cargo.toml b/framework/scenario/Cargo.toml index 0e13cb71dd..796ab19bf0 100644 --- a/framework/scenario/Cargo.toml +++ b/framework/scenario/Cargo.toml @@ -21,7 +21,7 @@ base64 = "0.22" num-bigint = "0.4" num-traits = "0.2" hex = "0.4" -bech32 = "0.9" +bech32 = "0.11" log = "0.4.17" sha2 = "0.10.6" serde = "1.0" diff --git a/framework/scenario/src/bech32.rs b/framework/scenario/src/bech32.rs index aa224cee95..ef934cf225 100644 --- a/framework/scenario/src/bech32.rs +++ b/framework/scenario/src/bech32.rs @@ -1,10 +1,9 @@ -use bech32::{FromBase32, ToBase32, Variant}; +use bech32::{Bech32, Hrp}; use multiversx_sc::types::heap::Address; pub fn decode(bech32_address: &str) -> Address { - let (_, dest_address_bytes_u5, _) = bech32::decode(bech32_address) + let (_hrp, dest_address_bytes) = bech32::decode(bech32_address) .unwrap_or_else(|err| panic!("bech32 decode error for {bech32_address}: {err}")); - let dest_address_bytes = Vec::::from_base32(&dest_address_bytes_u5).unwrap(); if dest_address_bytes.len() != 32 { panic!("Invalid address length after decoding") } @@ -13,6 +12,6 @@ pub fn decode(bech32_address: &str) -> Address { } pub fn encode(address: &Address) -> String { - bech32::encode("erd", address.as_bytes().to_base32(), Variant::Bech32) - .expect("bech32 encode error") + let hrp = Hrp::parse("erd").expect("invalid hrp"); + bech32::encode::(hrp, address.as_bytes()).expect("bech32 encode error") } diff --git a/sdk/core/Cargo.toml b/sdk/core/Cargo.toml index e84f8cd4cb..2387e4cce8 100644 --- a/sdk/core/Cargo.toml +++ b/sdk/core/Cargo.toml @@ -31,7 +31,7 @@ hex = "0.4.3" base64 = "0.22" pbkdf2 = { version = "0.12.2", default-features = false } zeroize = "1.4.2" -bech32 = "0.9" +bech32 = "0.11" itertools = "0.13.0" pem = "3.0.2" log = "0.4.17" diff --git a/sdk/core/src/crypto/public_key.rs b/sdk/core/src/crypto/public_key.rs index 89b5211262..473a0388fe 100644 --- a/sdk/core/src/crypto/public_key.rs +++ b/sdk/core/src/crypto/public_key.rs @@ -2,7 +2,7 @@ use std::fmt::Display; use super::private_key::PrivateKey; use anyhow::Result; -use bech32::{self, ToBase32, Variant}; +use bech32::{self, Bech32, Hrp}; use serde::{ de::{Deserialize, Deserializer}, ser::{Serialize, Serializer}, @@ -23,7 +23,8 @@ impl PublicKey { } pub fn to_address(&self) -> Result { - let address = bech32::encode("erd", self.0.to_base32(), Variant::Bech32)?; + let hrp = Hrp::parse("erd")?; + let address = bech32::encode::(hrp, &self.0)?; Ok(address) } diff --git a/sdk/core/src/data/address.rs b/sdk/core/src/data/address.rs index f8ac4212c3..49d92ea608 100644 --- a/sdk/core/src/data/address.rs +++ b/sdk/core/src/data/address.rs @@ -2,7 +2,7 @@ use std::fmt::{Debug, Display}; use crate::crypto::public_key::PublicKey; use anyhow::Result; -use bech32::{FromBase32, ToBase32, Variant}; +use bech32::{Bech32, Hrp}; use serde::{ de::{Deserialize, Deserializer}, ser::{Serialize, Serializer}, @@ -21,8 +21,7 @@ impl Address { } pub fn from_bech32_string(bech32: &str) -> Result { - let (_, data, _) = bech32::decode(bech32)?; - let data = Vec::::from_base32(&data)?; + let (_hrp, data) = bech32::decode(bech32)?; let mut bits: [u8; 32] = [0u8; 32]; bits.copy_from_slice(&data); @@ -31,7 +30,8 @@ impl Address { } pub fn to_bech32_string(&self) -> Result { - let address = bech32::encode("erd", self.0.to_base32(), Variant::Bech32)?; + let hrp = Hrp::parse("erd")?; + let address = bech32::encode::(hrp, &self.0)?; Ok(address) } diff --git a/sdk/scenario-format/Cargo.toml b/sdk/scenario-format/Cargo.toml index b66e3403ce..a79c6c31a7 100644 --- a/sdk/scenario-format/Cargo.toml +++ b/sdk/scenario-format/Cargo.toml @@ -20,4 +20,4 @@ num-bigint = "0.4" num-traits = "0.2" hex = "0.4" sha3 = "0.10.8" -bech32 = "0.9.0" +bech32 = "0.11.0" diff --git a/sdk/scenario-format/src/value_interpreter/functions.rs b/sdk/scenario-format/src/value_interpreter/functions.rs index 32895e84d7..b4ce547ad7 100644 --- a/sdk/scenario-format/src/value_interpreter/functions.rs +++ b/sdk/scenario-format/src/value_interpreter/functions.rs @@ -1,5 +1,4 @@ use crate::value_interpreter::*; -use bech32::FromBase32; use sha3::{Digest, Keccak256}; pub const SC_ADDRESS_NUM_LEADING_ZEROS: usize = 8; @@ -71,6 +70,6 @@ pub(crate) fn sc_address_expression(input: &str, vm_type: &VMIdentifier) -> Vec< } pub(crate) fn bech32(input: &str) -> Vec { - let (_, decoded, _) = bech32::decode(input).expect("bech32 decode error"); - Vec::::from_base32(&decoded).expect("bech32 base64 decode error") + let (_hrp, decoded) = bech32::decode(input).expect("bech32 decode error"); + decoded } diff --git a/tools/mxpy-snippet-generator/Cargo.toml b/tools/mxpy-snippet-generator/Cargo.toml index 58236c7f78..838f8a1dc2 100644 --- a/tools/mxpy-snippet-generator/Cargo.toml +++ b/tools/mxpy-snippet-generator/Cargo.toml @@ -14,7 +14,7 @@ version = "0.52.3" path = "../../framework/base" [dependencies] -bech32 = "0.9" +bech32 = "0.11" num-bigint = "0.4" num-traits = "0.2" hex = "0.4" diff --git a/tools/mxpy-snippet-generator/src/helper_types.rs b/tools/mxpy-snippet-generator/src/helper_types.rs index d2cb746a51..e012ef2cb6 100644 --- a/tools/mxpy-snippet-generator/src/helper_types.rs +++ b/tools/mxpy-snippet-generator/src/helper_types.rs @@ -1,4 +1,3 @@ -use bech32::FromBase32; use multiversx_sc::types::heap::Address; use crate::constants::*; @@ -79,8 +78,7 @@ impl TransactionType { } pub fn bech32_to_bytes(bech32_address: &str) -> Address { - let (_, dest_address_bytes_u5, _) = bech32::decode(bech32_address).unwrap(); - let dest_address_bytes = Vec::::from_base32(&dest_address_bytes_u5).unwrap(); + let (_hrp, dest_address_bytes) = bech32::decode(bech32_address).unwrap(); if dest_address_bytes.len() != ADDRESS_LEN { panic!("Invalid address length after decoding") } From 48a41f93c7fd2afbe83c0158866d704a26ea01e7 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 27 Aug 2024 12:56:25 +0300 Subject: [PATCH 42/52] unified - whitebox token_merge --- .../tests/token_merge_module_whitebox_test.rs | 966 ++++++++---------- 1 file changed, 420 insertions(+), 546 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index 5cc2180d01..51cd7fa6df 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -1,5 +1,3 @@ -#![allow(deprecated)] // TODO: migrate to unified syntax at some point - use multiversx_sc_scenario::imports::*; use multiversx_sc_modules::token_merge::{ @@ -7,18 +5,15 @@ use multiversx_sc_modules::token_merge::{ }; use use_module::token_merge_mod_impl::{CustomAttributes, TokenMergeModImpl}; -const OWNER_ADDRESS_EXPR: &str = "address:owner"; -const USER_ADDRESS_EXPR: &str = "address:user"; +const OWNER_ADDRESS_EXPR: TestAddress = TestAddress::new("owner"); +const USER_ADDRESS_EXPR: TestAddress = TestAddress::new("user"); -const USE_MODULE_ADDRESS_EXPR: &str = "sc:use-module"; -const USE_MODULE_PATH_EXPR: &str = "mxsc:output/use-module.mxsc.json"; +const USE_MODULE_ADDRESS_EXPR: TestSCAddress = TestSCAddress::new("use-module"); +const USE_MODULE_PATH_EXPR: MxscPath = MxscPath::new("mxsc:output/use-module.mxsc.json"); -const MERGED_TOKEN_ID_EXPR: &str = "str:MERGED-123456"; -const MERGED_TOKEN_ID: &[u8] = b"MERGED-123456"; -const NFT_TOKEN_ID_EXPR: &str = "str:NFT-123456"; -const NFT_TOKEN_ID: &[u8] = b"NFT-123456"; -const FUNGIBLE_TOKEN_ID_EXPR: &str = "str:FUN-123456"; -const FUNGIBLE_TOKEN_ID: &[u8] = b"FUN-123456"; +const MERGED_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("MERGED-123456"); +const NFT_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("NFT-123456"); +const FUNGIBLE_TOKEN_ID_EXPR: TestTokenIdentifier = TestTokenIdentifier::new("FUN-123456"); const NFT_AMOUNT: u64 = 1; const FUNGIBLE_AMOUNT: u64 = 100; @@ -43,561 +38,462 @@ fn world() -> ScenarioWorld { fn test_token_merge() { let mut world = world(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); - let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTBurn".to_string(), ]; - - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) - .esdt_nft_all_properties( - NFT_TOKEN_ID_EXPR, - FIRST_NFT_NONCE, - NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - FIRST_ROYALTIES, - None::, - None, - Vec::from(FIRST_URIS), - ) - .esdt_nft_all_properties( - NFT_TOKEN_ID_EXPR, - SECOND_NFT_NONCE, - NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - SECOND_ROYALTIES, - None::, - None, - Vec::from(SECOND_URIS), - ), - ) - .put_account( - USE_MODULE_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(use_module_code) - .owner(OWNER_ADDRESS_EXPR) - .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), - ), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + let first_uris = FIRST_URIS + .iter() + .map(|first_uri| managed_buffer!(first_uri)) + .collect(); + let second_uris = SECOND_URIS + .iter() + .map(|second_uri| managed_buffer!(second_uri)) + .collect(); + + world.account(OWNER_ADDRESS_EXPR).nonce(1); + world + .account(USER_ADDRESS_EXPR) + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None::
, + (), + first_uris, + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None::
, + (), + second_uris, + ); + + world + .account(USE_MODULE_ADDRESS_EXPR) + .nonce(1) + .code(USE_MODULE_PATH_EXPR) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles); + + world + .tx() + .from(OWNER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .whitebox(use_module::contract_obj, |sc| { sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + .set_token_id(MERGED_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); + .insert(NFT_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }, - ); + .insert(FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier()); + }); // merge two NFTs let nft_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(nft_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(nft_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); assert_eq!(merged_token.token_nonce, 1); assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(MERGED_TOKEN_ID), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); + let expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } assert_eq!( merged_token_data.royalties, managed_biguint!(SECOND_ROYALTIES) ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - MERGED_TOKEN_ID_EXPR, - 1, - NFT_AMOUNT, - Option::<&Empty>::None, - ), - )); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT, &Empty); - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); + FIRST_ATTRIBUTES, + ); - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - ), - )); + SECOND_ATTRIBUTES, + ); // split nfts - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( - MERGED_TOKEN_ID_EXPR, - 1, - NFT_AMOUNT, - ), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |sc| { let output_tokens = sc.split_tokens_endpoint(); - let mut expected_output_tokens = ManagedVec::new(); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - assert_eq!(output_tokens, expected_output_tokens); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + let expected_output_tokens = vec![ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; + assert_eq!(output_tokens, expected_output_tokens.into()); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); + FIRST_ATTRIBUTES, + ); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - ), - )); + SECOND_ATTRIBUTES, + ); // merge the NFT with fungible let esdt_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), - nonce: 0u64.into(), - esdt_value: FUNGIBLE_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0u64, FUNGIBLE_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(esdt_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(esdt_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); assert_eq!(merged_token.token_nonce, 2); assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(MERGED_TOKEN_ID), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 2, ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); + let expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } assert_eq!( merged_token_data.royalties, managed_biguint!(FIRST_ROYALTIES) ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - MERGED_TOKEN_ID_EXPR, - 2, - NFT_AMOUNT, - Option::<&Empty>::None, - ), - )); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 2, NFT_AMOUNT, &Empty); // merge NFT with an already merged token let combined_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: MERGED_TOKEN_ID.into(), - nonce: 2u64.into(), - esdt_value: NFT_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 2u64, NFT_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(combined_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(combined_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); assert_eq!(merged_token.token_nonce, 3); assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(MERGED_TOKEN_ID), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.into(), 3, ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); + let expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } assert_eq!( merged_token_data.royalties, managed_biguint!(SECOND_ROYALTIES) ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - MERGED_TOKEN_ID_EXPR, - 3, - NFT_AMOUNT, - Option::<&Empty>::None, - ), - )); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( - MERGED_TOKEN_ID_EXPR, - 3, - NFT_AMOUNT, - ), - |sc| { + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 3, NFT_AMOUNT, &Empty); + + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 3, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |sc| { let output_tokens = sc.split_tokens_endpoint(); - let mut expected_output_tokens = ManagedVec::new(); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); - expected_output_tokens.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - - assert_eq!(output_tokens, expected_output_tokens); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + let expected_output_tokens = vec![ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; + + assert_eq!(output_tokens, expected_output_tokens.into()); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); + FIRST_ATTRIBUTES, + ); - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - ), - )); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT), - )); + SECOND_ATTRIBUTES, + ); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT); } #[test] fn test_partial_split() { let mut world = world(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); - let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTBurn".to_string(), ]; - - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) - .esdt_nft_all_properties( - NFT_TOKEN_ID_EXPR, - FIRST_NFT_NONCE, - NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - FIRST_ROYALTIES, - None::, - None, - Vec::from(FIRST_URIS), - ) - .esdt_nft_all_properties( - NFT_TOKEN_ID_EXPR, - SECOND_NFT_NONCE, - NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - SECOND_ROYALTIES, - None::, - None, - Vec::from(SECOND_URIS), - ), - ) - .put_account( - USE_MODULE_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(use_module_code) - .owner(OWNER_ADDRESS_EXPR) - .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), - ), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + let first_uris = FIRST_URIS + .iter() + .map(|first_uri| managed_buffer!(first_uri)) + .collect(); + let second_uris = SECOND_URIS + .iter() + .map(|second_uri| managed_buffer!(second_uri)) + .collect(); + + world.account(OWNER_ADDRESS_EXPR).nonce(1); + world + .account(USER_ADDRESS_EXPR) + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None::, + (), + first_uris, + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None::, + (), + second_uris, + ); + + world + .account(USE_MODULE_ADDRESS_EXPR) + .nonce(1) + .code(USE_MODULE_PATH_EXPR) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles); + + world + .tx() + .from(OWNER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .whitebox(use_module::contract_obj, |sc| { sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); - let _ = sc - .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }, - ); + .set_token_id(MERGED_TOKEN_ID_EXPR.to_token_identifier()); + sc.mergeable_tokens_whitelist() + .insert(NFT_TOKEN_ID_EXPR.to_token_identifier()); + sc.mergeable_tokens_whitelist() + .insert(FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier()); + }); // merge 2 NFTs and a fungible token let esdt_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: FUNGIBLE_TOKEN_ID.into(), - nonce: 0u64.into(), - esdt_value: FUNGIBLE_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0u64, FUNGIBLE_AMOUNT), ]; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(esdt_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(esdt_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); assert_eq!(merged_token.token_nonce, 1); assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(MERGED_TOKEN_ID), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT), - )); + let expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); - }, - ); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } + }); // split part of the fungible token - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( - MERGED_TOKEN_ID_EXPR, - 1, - NFT_AMOUNT, - ), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |sc| { let mut tokens_to_remove = ManagedVec::new(); tokens_to_remove.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), 0, managed_biguint!(40), )); - let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); + let output_payments = sc.split_token_partial_endpoint(tokens_to_remove); let mut expected_output_payments = ManagedVec::new(); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), 0, managed_biguint!(40), )); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(MERGED_TOKEN_ID), + MERGED_TOKEN_ID_EXPR.to_token_identifier(), 2, managed_biguint!(NFT_AMOUNT), )); assert_eq!(output_payments, expected_output_payments); - }, - ); + }); // fully remove instance - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(USER_ADDRESS_EXPR).esdt_transfer( - MERGED_TOKEN_ID_EXPR, - 2, - NFT_AMOUNT, - ), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .payment(TestEsdtTransfer(MERGED_TOKEN_ID_EXPR, 2, NFT_AMOUNT)) + .whitebox(use_module::contract_obj, |sc| { let mut tokens_to_remove = ManagedVec::new(); tokens_to_remove.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID_EXPR.to_token_identifier(), FIRST_NFT_NONCE, managed_biguint!(NFT_AMOUNT), )); @@ -605,12 +501,12 @@ fn test_partial_split() { let mut expected_output_payments = ManagedVec::new(); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), + NFT_TOKEN_ID_EXPR.to_token_identifier(), FIRST_NFT_NONCE, managed_biguint!(NFT_AMOUNT), )); expected_output_payments.push(EsdtTokenPayment::new( - managed_token_id!(MERGED_TOKEN_ID), + MERGED_TOKEN_ID_EXPR.to_token_identifier(), 3, managed_biguint!(NFT_AMOUNT), )); @@ -618,112 +514,102 @@ fn test_partial_split() { // check newest token attributes let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(MERGED_TOKEN_ID), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 3, ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(FUNGIBLE_TOKEN_ID), - 0, - managed_biguint!(FUNGIBLE_AMOUNT - 40), - )); + let expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT - 40), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } assert_eq!( merged_token_data.royalties, managed_biguint!(SECOND_ROYALTIES) ); - }, - ); + }); } #[test] fn test_custom_attributes() { let mut world = world(); - let use_module_whitebox = - WhiteboxContract::new(USE_MODULE_ADDRESS_EXPR, use_module::contract_obj); - let use_module_code = world.code_expression(USE_MODULE_PATH_EXPR); - let roles = vec![ "ESDTRoleNFTCreate".to_string(), "ESDTRoleNFTBurn".to_string(), ]; - world.set_state_step( - SetStateStep::new() - .put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)) - .put_account( - USER_ADDRESS_EXPR, - Account::new() - .nonce(1) - .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) - .esdt_nft_all_properties( - NFT_TOKEN_ID_EXPR, - FIRST_NFT_NONCE, - NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - FIRST_ROYALTIES, - None::, - None, - Vec::from(FIRST_URIS), - ) - .esdt_nft_all_properties( - NFT_TOKEN_ID_EXPR, - SECOND_NFT_NONCE, - NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - SECOND_ROYALTIES, - None::, - None, - Vec::from(SECOND_URIS), - ), - ) - .put_account( - USE_MODULE_ADDRESS_EXPR, - Account::new() - .nonce(1) - .code(use_module_code) - .owner(OWNER_ADDRESS_EXPR) - .esdt_roles(MERGED_TOKEN_ID_EXPR, roles), - ), - ); - - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new().from(OWNER_ADDRESS_EXPR), - |sc| { + let first_uris = FIRST_URIS + .iter() + .map(|first_uri| managed_buffer!(first_uri)) + .collect(); + let second_uris = SECOND_URIS + .iter() + .map(|second_uri| managed_buffer!(second_uri)) + .collect(); + world.account(OWNER_ADDRESS_EXPR).nonce(1); + world + .account(USER_ADDRESS_EXPR) + .nonce(1) + .esdt_balance(FUNGIBLE_TOKEN_ID_EXPR, FUNGIBLE_AMOUNT) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + FIRST_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(FIRST_ATTRIBUTES), + FIRST_ROYALTIES, + None::, + (), + first_uris, + ) + .esdt_nft_all_properties( + NFT_TOKEN_ID_EXPR, + SECOND_NFT_NONCE, + NFT_AMOUNT, + managed_buffer!(SECOND_ATTRIBUTES), + SECOND_ROYALTIES, + None::, + (), + second_uris, + ); + world + .account(USE_MODULE_ADDRESS_EXPR) + .nonce(1) + .code(USE_MODULE_PATH_EXPR) + .owner(OWNER_ADDRESS_EXPR) + .esdt_roles(MERGED_TOKEN_ID_EXPR, roles); + + world + .tx() + .from(OWNER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .whitebox(use_module::contract_obj, |sc| { sc.merged_token() - .set_token_id(managed_token_id!(MERGED_TOKEN_ID)); + .set_token_id(MERGED_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(NFT_TOKEN_ID)); + .insert(NFT_TOKEN_ID_EXPR.to_token_identifier()); let _ = sc .mergeable_tokens_whitelist() - .insert(managed_token_id!(FUNGIBLE_TOKEN_ID)); - }, - ); + .insert(FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier()); + }); // merge two NFTs let nft_transfers = vec![ - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: FIRST_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, - TxESDT { - esdt_token_identifier: NFT_TOKEN_ID.into(), - nonce: SECOND_NFT_NONCE.into(), - esdt_value: NFT_AMOUNT.into(), - }, + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), ]; let expected_attributes = CustomAttributes { @@ -731,39 +617,41 @@ fn test_custom_attributes() { second: 10u64, }; - world.whitebox_call( - &use_module_whitebox, - ScCallStep::new() - .from(USER_ADDRESS_EXPR) - .multi_esdt_transfer(nft_transfers), - |sc| { + world + .tx() + .from(USER_ADDRESS_EXPR) + .to(USE_MODULE_ADDRESS_EXPR) + .multi_esdt(nft_transfers) + .whitebox(use_module::contract_obj, |sc| { let merged_token = sc.merge_tokens_custom_attributes_endpoint(); assert_eq!( merged_token.token_identifier, - managed_token_id!(MERGED_TOKEN_ID) + MERGED_TOKEN_ID_EXPR.to_token_identifier() ); assert_eq!(merged_token.token_nonce, 1); assert_eq!(merged_token.amount, managed_biguint!(NFT_AMOUNT)); let merged_token_data = sc.blockchain().get_esdt_token_data( - &managed_address!(&address_expr_to_address(USER_ADDRESS_EXPR)), - &managed_token_id!(MERGED_TOKEN_ID), + &USER_ADDRESS_EXPR.to_managed_address(), + &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let mut expected_uri = ArrayVec::new(); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - FIRST_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); - expected_uri.push(EsdtTokenPayment::new( - managed_token_id!(NFT_TOKEN_ID), - SECOND_NFT_NONCE, - managed_biguint!(NFT_AMOUNT), - )); + let expected_uri = [ + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), + TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), + ]; let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - assert_eq!(expected_uri, actual_uri.into_instances()); + for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { + let token_identifier_string = uri.token_identifier.to_string(); + let actual_transfer = TestEsdtTransfer( + TestTokenIdentifier::new(&token_identifier_string), + uri.token_nonce, + uri.amount.to_u64().unwrap(), + ); + + assert_eq!(expected, &actual_transfer); + } let actual_attributes: CustomAttributes = merged_token_data.decode_attributes(); assert_eq!(expected_attributes, actual_attributes); @@ -772,40 +660,26 @@ fn test_custom_attributes() { merged_token_data.royalties, managed_biguint!(SECOND_ROYALTIES) ); - }, - ); - - world.check_state_step(CheckStateStep::new().put_account( - USER_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( - MERGED_TOKEN_ID_EXPR, - 1, - NFT_AMOUNT, - Some(top_encode_to_vec_u8_or_panic(&expected_attributes)), - ), - )); + }); + + world + .check_account(USER_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes(MERGED_TOKEN_ID_EXPR, 1, NFT_AMOUNT, expected_attributes); - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT, - Some(FIRST_ATTRIBUTES), - ), - )); - - world.check_state_step(CheckStateStep::new().put_account( - USE_MODULE_ADDRESS_EXPR, - CheckAccount::new().esdt_nft_balance_and_attributes( + FIRST_ATTRIBUTES, + ); + world + .check_account(USE_MODULE_ADDRESS_EXPR) + .esdt_nft_balance_and_attributes( NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT, - Some(SECOND_ATTRIBUTES), - ), - )); -} - -fn address_expr_to_address(address_expr: &str) -> Address { - AddressValue::from(address_expr).to_address() + SECOND_ATTRIBUTES, + ); } From e2daf814025e18ddb82d47e4eed652caf98111b8 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 27 Aug 2024 15:06:47 +0300 Subject: [PATCH 43/52] verify_bls_aggregated_signature test fix --- ..._verify_bls_aggregated_signature.scen.json | 37 ++++++++++++------- .../basic-features/src/crypto_features.rs | 2 +- .../contract_base/wrappers/crypto_wrapper.rs | 4 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json index 46617194c5..d8e46f2389 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -19,22 +19,28 @@ }, { "step": "scCall", - "id": "1", + "id": "bls multi - ok", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_bls_aggregated_signature", "arguments": [ - "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", - "0x6d65737361676530", - "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + [ + "nested:0x95f1d96b582f35294eb7dd4589b158e108e1d94cd0dd71ef16140e9b37126ec52dac6f57397f1e041acd7bb77df1d214f9f894e3b7fbf7abeaabc9fab8ff5c2ef05f9841322f301fdb900ac59479c334ac76a2d4ff992cd49bc9b530c25ee293", + "nested:0x97aa2862418eb4ea74fddcb511eef9b771e07ff901e7e6abb35847a4bb81e58f189fc9bce4186c6129014fb43002300e959702ef4b9d0c32ebe4d795457095d65b5414efb36edbb8dc66d84a445a92472d4a31cedd4700d5ebb885eb11d3430b", + "nested:0x37b73265936a2aaafe652a4dd451a1851c2dbbb32208604787479b31033e2a354615562ea2a5488f9134843362477a139050a0e798dd5ce0f01b35b8d473454ae99633aadde9237f84c87eb366144cca4de3d2cc6acc35e522a3294bf1186800", + "nested:0xf46c10d114dcd3019dd4bcd4152fda678c56144eb177c67a6411213b86e206e4e56a9aad1eab0313b13031fda046d715ec4a02612b083dfae0d82a23b643e1a89756c0df3d65c27e87a9c1289628d1a8404f0668a3d87c7451ba1c78fc452693", + "nested:0xaa0a97917df9240c537c89e873d7baa5ce1796e8fedfb23cf682b80fa19b8baae35af3754f9b8149985cb2a1fbda0f02c2942d2c99d9af556c9a5e90b8170e6a96379a45dd69351abfb814a16b5665abb7ddb8b096ee9f273de81845cda9728a" + ], + "str:message0", + "0xae12858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x01" + "true" ], "status": "", "logs": "*", @@ -44,24 +50,29 @@ }, { "step": "scCall", - "id": "2", + "id": "bls multi - fail", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_bls_aggregated_signature", "arguments": [ - "0x9cfb3532e21737e8f9eec99b04f000b27ec277d2477d881273ea07d3af96dc3e153878ed002bcd10e8320242caab49024b8c934b437b17e743b9706757f0e7b2e9fb28295d7f82af8875e0776ae8918c25206519b3f73dcbbd53cafeb5cec716", - "0x6d657373616765323133", - "0x84737000b07fbce9b649449f9de6aae76347f5bb5eefcd017f53e874601ccf5f96c9b4ca5f85ea5f6ef6243c38c9ab99" + [ + "nested:0x95f1d96b582f35294eb7dd4589b158e108e1d94cd0dd71ef16140e9b37126ec52dac6f57397f1e041acd7bb77df1d214f9f894e3b7fbf7abeaabc9fab8ff5c2ef05f9841322f301fdb900ac59479c334ac76a2d4ff992cd49bc9b530c25ee293", + "nested:0x97aa2862418eb4ea74fddcb511eef9b771e07ff901e7e6abb35847a4bb81e58f189fc9bce4186c6129014fb43002300e959702ef4b9d0c32ebe4d795457095d65b5414efb36edbb8dc66d84a445a92472d4a31cedd4700d5ebb885eb11d3430b", + "nested:0x37b73265936a2aaafe652a4dd451a1851c2dbbb32208604787479b31033e2a354615562ea2a5488f9134843362477a139050a0e798dd5ce0f01b35b8d473454ae99633aadde9237f84c87eb366144cca4de3d2cc6acc35e522a3294bf1186800", + "nested:0xf46c10d114dcd3019dd4bcd4152fda678c56144eb177c67a6411213b86e206e4e56a9aad1eab0313b13031fda046d715ec4a02612b083dfae0d82a23b643e1a89756c0df3d65c27e87a9c1289628d1a8404f0668a3d87c7451ba1c78fc452693", + "nested:0xaa0a97917df9240c537c89e873d7baa5ce1796e8fedfb23cf682b80fa19b8baae35af3754f9b8149985cb2a1fbda0f02c2942d2c99d9af556c9a5e90b8170e6a96379a45dd69351abfb814a16b5665abb7ddb8b096ee9f273de81845cda9728a" + ], + "str:message0", + "0x0012858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { - "out": [ - "0x00" - ], - "status": "", + "out": [], + "status": "10", + "message": "str:err blsSignatureDeserialize 0012858363e8caa5b398d3febdd7bc01bc2fae1fef8f486ff4d84a5f3342f2d38085904eb10b73c0879a45d23585ce8f", "logs": "*", "gas": "*", "refund": "*" diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 4a9c7dbb6f..8da0c83984 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -92,7 +92,7 @@ pub trait CryptoFeatures { #[label("crypto-ei-1.4")] fn verify_bls_aggregated_signature( &self, - key: ManagedBuffer, + key: ManagedVec, message: ManagedBuffer, signature: ManagedBuffer, ) -> bool { diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index 76b8fcd996..eb98f93a56 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -5,7 +5,7 @@ use crate::{ use_raw_handle, CryptoApi, CryptoApiImpl, StaticVarApiImpl, KECCAK256_RESULT_LEN, SHA256_RESULT_LEN, }, - types::{ManagedBuffer, ManagedByteArray, ManagedType, MessageHashType}, + types::{ManagedBuffer, ManagedByteArray, ManagedType, ManagedVec, MessageHashType}, }; #[derive(Default)] @@ -158,7 +158,7 @@ where pub fn verify_bls_aggregated_signature( &self, - key: &ManagedBuffer, + key: &ManagedVec>, message: &ManagedBuffer, signature: &ManagedBuffer, ) -> bool { From b13757be1ab878b6c1320770855476bcc74a0d8e Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Wed, 28 Aug 2024 12:37:06 +0300 Subject: [PATCH 44/52] unified - compare expected_uri with serialized merged_token_data uri --- .../tests/token_merge_module_whitebox_test.rs | 176 +++++++++--------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs index 51cd7fa6df..4b40f656c9 100644 --- a/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs +++ b/contracts/feature-tests/use-module/tests/token_merge_module_whitebox_test.rs @@ -124,23 +124,21 @@ fn test_token_merge() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -228,22 +226,21 @@ fn test_token_merge() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 2, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -280,23 +277,26 @@ fn test_token_merge() { &MERGED_TOKEN_ID_EXPR.into(), 3, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -436,23 +436,26 @@ fn test_partial_split() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); }); // split part of the fungible token @@ -518,22 +521,21 @@ fn test_partial_split() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 3, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(FUNGIBLE_TOKEN_ID_EXPR, 0, FUNGIBLE_AMOUNT - 40), - ]; + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + FUNGIBLE_TOKEN_ID_EXPR.to_token_identifier(), + 0, + managed_biguint!(FUNGIBLE_AMOUNT - 40), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); assert_eq!( merged_token_data.royalties, @@ -636,22 +638,20 @@ fn test_custom_attributes() { &MERGED_TOKEN_ID_EXPR.to_token_identifier(), 1, ); - let expected_uri = [ - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, FIRST_NFT_NONCE, NFT_AMOUNT), - TestEsdtTransfer(NFT_TOKEN_ID_EXPR, SECOND_NFT_NONCE, NFT_AMOUNT), - ]; - + let expected_uri = ArrayVec::from([ + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + FIRST_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + EsdtTokenPayment::new( + NFT_TOKEN_ID_EXPR.to_token_identifier(), + SECOND_NFT_NONCE, + managed_biguint!(NFT_AMOUNT), + ), + ]); let actual_uri = MergedTokenInstances::decode_from_first_uri(&merged_token_data.uris); - for (expected, uri) in expected_uri.iter().zip(actual_uri.into_instances()) { - let token_identifier_string = uri.token_identifier.to_string(); - let actual_transfer = TestEsdtTransfer( - TestTokenIdentifier::new(&token_identifier_string), - uri.token_nonce, - uri.amount.to_u64().unwrap(), - ); - - assert_eq!(expected, &actual_transfer); - } + assert_eq!(expected_uri, *actual_uri.into_instances()); let actual_attributes: CustomAttributes = merged_token_data.decode_attributes(); assert_eq!(expected_attributes, actual_attributes); From 1d7f49587f3066df32ba4218b8261591305f9080 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 16:03:58 +0300 Subject: [PATCH 45/52] fixed returnsNewTokenIdentifier interactor --- framework/snippets/src/network_response.rs | 23 +++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index d505e7a525..4d828e12c7 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -103,25 +103,31 @@ fn process_new_deployed_address(tx: &TransactionOnNetwork) -> Option
{ } fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option { + let original_tx_data = String::from_utf8(base64_decode(tx.data.as_ref().unwrap())).unwrap(); + for scr in tx.smart_contract_results.iter() { if scr.sender.to_bech32_string().unwrap() != ESDTSystemSCAddress.to_bech32_string() { continue; } - let Some(prev_tx) = tx + let prev_tx_data: &str = if let Some(prev_tx) = tx .smart_contract_results .iter() .find(|e| e.hash == scr.prev_tx_hash) - else { + { + prev_tx.data.as_ref() + } else if &scr.prev_tx_hash == tx.hash.as_ref().unwrap() { + &original_tx_data + } else { continue; }; - let is_issue_fungible = prev_tx.data.starts_with("issue@"); - let is_issue_semi_fungible = prev_tx.data.starts_with("issueSemiFungible@"); - let is_issue_non_fungible = prev_tx.data.starts_with("issueNonFungible@"); - let is_register_meta_esdt = prev_tx.data.starts_with("registerMetaESDT@"); + let is_issue_fungible = prev_tx_data.starts_with("issue@"); + let is_issue_semi_fungible = prev_tx_data.starts_with("issueSemiFungible@"); + let is_issue_non_fungible = prev_tx_data.starts_with("issueNonFungible@"); + let is_register_meta_esdt = prev_tx_data.starts_with("registerMetaESDT@"); let is_register_and_set_all_roles_esdt = - prev_tx.data.starts_with("registerAndSetAllRoles@"); + prev_tx_data.starts_with("registerAndSetAllRoles@"); if !is_issue_fungible && !is_issue_semi_fungible @@ -135,12 +141,11 @@ fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option Date: Thu, 29 Aug 2024 17:05:05 +0300 Subject: [PATCH 46/52] added fix for sc calls creating systemSC issues --- sdk/core/src/gateway/gateway_tx_retrieve.rs | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index 821713f972..c5bbda6adf 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -14,6 +14,7 @@ impl GatewayProxy { let mut retries = 0; let mut backoff_delay = Duration::from_secs_f32(INITIAL_BACKOFF_DELAY); let start_time = Instant::now(); + let mut issue_found = false; loop { match self.get_transaction_status(&tx_hash).await { @@ -26,6 +27,20 @@ impl GatewayProxy { .get_transaction_info_with_results(&tx_hash) .await .unwrap(); + + if transaction_info_with_results.smart_contract_results.len() > 0 + && issue_found == false + { + let first_scr = + &transaction_info_with_results.smart_contract_results[0]; + + if GatewayProxy::is_issue_tx(&first_scr.data) { + issue_found = true; + tokio::time::sleep(Duration::from_secs(30)).await; + continue; + } + } + info!( "Transaction retrieved successfully, with status {}: {:#?}", status, transaction_info_with_results @@ -60,4 +75,12 @@ impl GatewayProxy { ); TransactionOnNetwork::default() } + + fn is_issue_tx(data: &str) -> bool { + data.starts_with("issue@") + || data.starts_with("issueSemiFungible@") + || data.starts_with("issueNonFungible@") + || data.starts_with("registerMetaESDT@") + || data.starts_with("registerAndSetAllRoles@") + } } From 044153613ea4dbedd53822b4ff0681e341b99ec0 Mon Sep 17 00:00:00 2001 From: Andrei Vasilescu Date: Thu, 29 Aug 2024 17:07:39 +0300 Subject: [PATCH 47/52] fixed clippy warnings --- sdk/core/src/gateway/gateway_tx_retrieve.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/core/src/gateway/gateway_tx_retrieve.rs b/sdk/core/src/gateway/gateway_tx_retrieve.rs index c5bbda6adf..452d37b3e0 100644 --- a/sdk/core/src/gateway/gateway_tx_retrieve.rs +++ b/sdk/core/src/gateway/gateway_tx_retrieve.rs @@ -28,8 +28,10 @@ impl GatewayProxy { .await .unwrap(); - if transaction_info_with_results.smart_contract_results.len() > 0 - && issue_found == false + if !transaction_info_with_results + .smart_contract_results + .is_empty() + && !issue_found { let first_scr = &transaction_info_with_results.smart_contract_results[0]; From d31ffa7ecf04343ed6e913391dfabf8354f0572f Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 30 Aug 2024 11:37:13 +0300 Subject: [PATCH 48/52] crypto EI 1.4 tests ignored --- .../basic-features/tests/basic_features_scenario_go_test.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs index 3a7a5dc515..58bee7c1da 100644 --- a/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs +++ b/contracts/feature-tests/basic-features/tests/basic_features_scenario_go_test.rs @@ -85,11 +85,13 @@ fn crypto_verify_bls_go() { } #[test] +#[ignore = "requires EI 1.4 in mx-scenario-go"] fn crypto_verify_bls_share_go() { world().run("scenarios/crypto_verify_bls_share.scen.json"); } #[test] +#[ignore = "requires EI 1.4 in mx-scenario-go"] fn crypto_verify_bls_aggregated_go() { world().run("scenarios/crypto_verify_bls_aggregated_signature.scen.json"); } @@ -105,6 +107,7 @@ fn crypto_verify_secp_256_k_1_go() { } #[test] +#[ignore = "requires EI 1.4 in mx-scenario-go"] fn crypto_verify_secp_256_r_1_go() { world().run("scenarios/crypto_verify_secp256r1.scen.json"); } From 4517c25151fd0c0c69ea1a49be7052d449d4e7f0 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 30 Aug 2024 17:38:57 +0300 Subject: [PATCH 49/52] crypto_verify_secp256r1 test fix --- .../crypto_verify_secp256r1.scen.json | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index 0de6016ef6..c1287b32d9 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -19,22 +19,22 @@ }, { "step": "scCall", - "id": "1", + "id": "secp256r1 - ok", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ - "0x03e4d20902182b89cd5ed7984ebcf063f2fd2508d9f034e4109be487be9e2cf54d", - "0xa607fab72e13d6b625942bd5c56cc32792c2c7c7f16053b2fb6d62dd9cf36fdacf9d5a8af3537eaf5eb93335b36cf8f1d6e5bb2dfffce9055a2608d5e1a5b839eacf36dd5dec6d2fa156133acf064cc26487d543873f3b3837a3c09b5f4cb509bbc6585d", - "0xd5065c32582bf0bc8f96b34177cbf47f61d4705d64daaebff884693b6dd94afd50d3ac647aeb14d325c28bb00ab68b23280c1c480cac0e72b5a58176ac8cd1b9" + "0x02bc52274edebbef8878eacc4d1e0ed4fb213e5b0737389701ae8d59c403325720", + "0xbf9facf48b2219db73b50c7ff59ceef2ada56632c71afc555d6bb4072d7634d1d9353acd53517ffb9a06935a89a6454fcaa40c69becf9f8029a271fd252ea55307d00d6e97a30719d48d6b7f993af24e9c54381cba02a113238eaee9d741cababeb21aaf", + "0xc7877497444274267a4ea6f42deefde23a12e44f1ec1b437018e5c0e2834ce376dec1b81ebeacf5fbc6882e69af7cafad47bbb96cfb09e8d77d12afff7543052" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { "out": [ - "0x01" + "true" ], "status": "", "logs": "*", @@ -44,24 +44,23 @@ }, { "step": "scCall", - "id": "2", + "id": "secp256r1 - fail", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_secp256r1_signature", "arguments": [ - "0x04a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5ca1d22fe57c6103dbaac10cf15d15c0791cab8bb9a04f800e4d215276cb3e008", - "0x00", - "0x3045022100fab29dbcb623e7e96f44665f312b89ffdb9e4d2e2f53353236fbbcf57b2f49bf02203d6f9c63df8be43121042970a549a2d3baeca093fd37b726ddcc0924638409f5" + "0x02bc52274edebbef8878eacc4d1e0ed4fb213e5b0737389701ae8d59c403325720", + "0xbf9facf48b2219db73b50c7ff59ceef2ada56632c71afc555d6bb4072d7634d1d9353acd53517ffb9a06935a89a6454fcaa40c69becf9f8029a271fd252ea55307d00d6e97a30719d48d6b7f993af24e9c54381cba02a113238eaee9d741cababeb21aaf", + "0x00877497444274267a4ea6f42deefde23a12e44f1ec1b437018e5c0e2834ce376dec1b81ebeacf5fbc6882e69af7cafad47bbb96cfb09e8d77d12afff7543052" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { - "out": [ - "0x00" - ], - "status": "", + "out": [], + "status": "10", + "message": "str:signature verification failed", "logs": "*", "gas": "*", "refund": "*" From f58b4f3fbcb8f87950a9be593a0f885e32f9de2b Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 1 Sep 2024 01:55:33 +0300 Subject: [PATCH 50/52] crypto_verify_bls_share test fix --- .../crypto_verify_bls_share.scen.json | 44 ++++--------------- 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json index 046b015d86..6aa653a9cd 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -1,6 +1,6 @@ { "name": "crypto", - "comment": "does not currently work with scenarios-rs, because verify_bls function is not yet mocked", + "comment": "does not currently work with scenarios-rs, because function is not yet mocked", "gasSchedule": "v3", "steps": [ { @@ -19,7 +19,7 @@ }, { "step": "scCall", - "id": "1", + "id": "verify_bls_signature_share - Ok", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", @@ -44,49 +44,23 @@ }, { "step": "scCall", - "id": "2", + "id": "verify_bls_signature_share - Fail", "tx": { "from": "address:an_account", "to": "sc:basic-features-crypto", "function": "verify_bls_signature_share", "arguments": [ - "0x2c9a358953f61d34401d7ee4175eec105c476b18baacab371e2f47270035b539d84ad79ba587552b7e38802be00ff7148fc2a9c7a7034ff1e63ee24602ee952235ad14ca7d36e2be617fb2c99ed22a7a2729d86ae9fbb4df06f957ba07fec50e", - "0x1e46d9cbb995e30b82485525c29f80ac78aca295a6e88a11c3df8f9a445494bb", - "0xbe8c460db180d6254c712ead3aa81935bc9be15b919dd45cb152b3dece04762569778c5e70e7af03fa1c66409d4f4711" - ], - "gasLimit": "50,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "0x00" - ], - "status": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, - { - "step": "scCall", - "id": "2", - "tx": { - "from": "address:an_account", - "to": "sc:basic-features", - "function": "verify_bls_aggregated_signature", - "arguments": [ - "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", - "0x6d65737361676520746f206265207369676e6564", - "0xaf32a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + "0x3e886a4c6e109a151f4105aee65a5192d150ef1fa68d3cd76964a0b086006dbe4324c989deb0e4416c6d6706db1b1910eb2732f08842fb4886067b9ed191109ac2188d76002d2e11da80a3f0ea89fee6b59c834cc478a6bd49cb8a193b1abb16", + "0xe96bd0f36b70c5ccc0c4396343bd7d8255b8a526c55fa1e218511fafe6539b8e", + "0xff725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f" ], "gasLimit": "50,000,000", "gasPrice": "0" }, "expect": { - "out": [ - "0x01" - ], - "status": "", + "out": [], + "status": "10", + "message": "str:err blsSignatureDeserialize ff725db195e37aa237cdbbda76270d4a229b6e7a3651104dc58c4349c0388e8546976fe54a04240530b99064e434c90f", "logs": "*", "gas": "*", "refund": "*" From d31643cc848e6e4671031da9283841e9d79fde70 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 1 Sep 2024 02:33:54 +0300 Subject: [PATCH 51/52] crypto functions that fail directly no longer return bool --- .../scenarios/crypto_verify_bls.scen.json | 32 ++++++++++++++++--- ..._verify_bls_aggregated_signature.scen.json | 6 ++-- .../crypto_verify_bls_share.scen.json | 6 ++-- .../crypto_verify_secp256r1.scen.json | 7 ++-- .../managed_decimal_logarithm.scen.json | 2 +- .../basic-features/src/crypto_features.rs | 8 ++--- framework/base/src/api/crypto_api.rs | 8 ++--- .../api/uncallable/crypto_api_uncallable.rs | 8 ++--- .../contract_base/wrappers/crypto_wrapper.rs | 25 +++++++++++---- .../src/api/core_api_vh/crypto_api_vh.rs | 8 ++--- .../wasm-adapter/src/api/crypto_api_node.rs | 24 +++++++++----- 11 files changed, 84 insertions(+), 50 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json index f5c6ef194c..fc67a3745b 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls.scen.json @@ -19,7 +19,7 @@ }, { "step": "scCall", - "id": "3", + "id": "verify_bls_signature - Ok", "tx": { "from": "address:an_account", "to": "sc:basic-features", @@ -33,14 +33,36 @@ "gasPrice": "0" }, "expect": { - "out": [ - "0x01" - ], + "out": [], "status": "", "logs": "*", "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "verify_bls_signature - Fail", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "verify_bls_signature", + "arguments": [ + "0xb5823f6e564251cc03ce7bad3da83e72576e92795d3500bba1acb30ec9a94dce87bb8aa794d67b2d61d15c33f28f6c0c23ba1dfcbf21e8f8b46286ff871afabac925303ddcaddce6254fcff6d3155797db40b3d3b5865e8fc0bd770b3d79b381", + "0x6d65737361676520746f206265207369676e6564", + "0x0032a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [], + "status": "10", + "message": "str:err blsSignatureDeserialize 0032a2ddf341c08d1eb7232f05dc34e4454155e676b58c40fddf9a036562ac2c01533d2d557cb49d73aa9d7a89744696", + "logs": "*", + "gas": "*", + "refund": "*" + } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json index d8e46f2389..546c0d4c9f 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_aggregated_signature.scen.json @@ -39,9 +39,7 @@ "gasPrice": "0" }, "expect": { - "out": [ - "true" - ], + "out": [], "status": "", "logs": "*", "gas": "*", @@ -79,4 +77,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json index 6aa653a9cd..fa7c21611b 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_bls_share.scen.json @@ -33,9 +33,7 @@ "gasPrice": "0" }, "expect": { - "out": [ - "0x01" - ], + "out": [], "status": "", "logs": "*", "gas": "*", @@ -67,4 +65,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json index c1287b32d9..1c35b46271 100644 --- a/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/crypto_verify_secp256r1.scen.json @@ -1,6 +1,5 @@ { "name": "crypto", - "comment": "", "gasSchedule": "v3", "steps": [ { @@ -33,9 +32,7 @@ "gasPrice": "0" }, "expect": { - "out": [ - "true" - ], + "out": [], "status": "", "logs": "*", "gas": "*", @@ -67,4 +64,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index da54f8ccec..065e92988c 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -24,7 +24,7 @@ "arguments": [ "23,000000000" ], - "gasLimit": "9,000,000", + "gasLimit": "25,000,000", "gasPrice": "0" }, "expect": { diff --git a/contracts/feature-tests/basic-features/src/crypto_features.rs b/contracts/feature-tests/basic-features/src/crypto_features.rs index 8da0c83984..0588146780 100644 --- a/contracts/feature-tests/basic-features/src/crypto_features.rs +++ b/contracts/feature-tests/basic-features/src/crypto_features.rs @@ -24,7 +24,7 @@ pub trait CryptoFeatures { key: ManagedBuffer, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto().verify_bls(&key, &message, &signature) } @@ -72,7 +72,7 @@ pub trait CryptoFeatures { key: ManagedBuffer, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto().verify_secp256r1(&key, &message, &signature) } @@ -83,7 +83,7 @@ pub trait CryptoFeatures { key: ManagedBuffer, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto() .verify_bls_signature_share(&key, &message, &signature) } @@ -95,7 +95,7 @@ pub trait CryptoFeatures { key: ManagedVec, message: ManagedBuffer, signature: ManagedBuffer, - ) -> bool { + ) { self.crypto() .verify_bls_aggregated_signature(&key, &message, &signature) } diff --git a/framework/base/src/api/crypto_api.rs b/framework/base/src/api/crypto_api.rs index 235e44919a..f6eaf80fe4 100644 --- a/framework/base/src/api/crypto_api.rs +++ b/framework/base/src/api/crypto_api.rs @@ -44,7 +44,7 @@ pub trait CryptoApiImpl: ManagedTypeApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); fn verify_ed25519_managed( &self, @@ -82,19 +82,19 @@ pub trait CryptoApiImpl: ManagedTypeApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); fn verify_bls_signature_share_managed( &self, key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); fn verify_bls_aggregated_signature_managed( &self, key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool; + ); } diff --git a/framework/base/src/api/uncallable/crypto_api_uncallable.rs b/framework/base/src/api/uncallable/crypto_api_uncallable.rs index bb42aa04bb..fe0547c5d7 100644 --- a/framework/base/src/api/uncallable/crypto_api_uncallable.rs +++ b/framework/base/src/api/uncallable/crypto_api_uncallable.rs @@ -42,7 +42,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } @@ -88,7 +88,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } @@ -97,7 +97,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } @@ -106,7 +106,7 @@ impl CryptoApiImpl for UncallableApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { unreachable!() } } diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index eb98f93a56..369cca1a63 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -61,7 +61,7 @@ where key: &ManagedBuffer, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_bls_managed( key.get_handle(), message.get_handle(), @@ -69,7 +69,9 @@ where ) } - /// Will crash if the verification fails. + /// Calls the Vm to verify ed25519 signature. + /// + /// Does not return result, will fail tx directly! /// /// The error comes straight form the VM, the message is "invalid signature". pub fn verify_ed25519( @@ -130,12 +132,15 @@ where ManagedBuffer::from_handle(new_handle) } + /// Calls the Vm to verify secp256r1 signature. + /// + /// Does not return result, will fail tx directly! pub fn verify_secp256r1( &self, key: &ManagedBuffer, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_secp256r1_managed( key.get_handle(), message.get_handle(), @@ -143,12 +148,15 @@ where ) } + /// Calls the Vm to verify BLS signature share. + /// + /// Does not return result, will fail tx directly! pub fn verify_bls_signature_share( &self, key: &ManagedBuffer, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_bls_signature_share_managed( key.get_handle(), message.get_handle(), @@ -156,14 +164,17 @@ where ) } + /// Calls the Vm to verify BLS aggregated signature. + /// + /// Does not return result, will fail tx directly! pub fn verify_bls_aggregated_signature( &self, - key: &ManagedVec>, + keys: &ManagedVec>, message: &ManagedBuffer, signature: &ManagedBuffer, - ) -> bool { + ) { A::crypto_api_impl().verify_bls_aggregated_signature_managed( - key.get_handle(), + keys.get_handle(), message.get_handle(), signature.get_handle(), ) diff --git a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs index aa4c2dab94..305b3d6be9 100644 --- a/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs +++ b/framework/scenario/src/api/core_api_vh/crypto_api_vh.rs @@ -53,7 +53,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_bls not implemented yet!") } @@ -105,7 +105,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_secp256r1 not implemented yet!") } @@ -114,7 +114,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_bls_signature_share not implemented yet!") } @@ -123,7 +123,7 @@ impl CryptoApiImpl for VMHooksApi { _key: Self::ManagedBufferHandle, _message: Self::ManagedBufferHandle, _signature: Self::ManagedBufferHandle, - ) -> bool { + ) { panic!("verify_bls_aggregated_signature not implemented yet!") } } diff --git a/framework/wasm-adapter/src/api/crypto_api_node.rs b/framework/wasm-adapter/src/api/crypto_api_node.rs index 0cbe24fad5..df62b30df9 100644 --- a/framework/wasm-adapter/src/api/crypto_api_node.rs +++ b/framework/wasm-adapter/src/api/crypto_api_node.rs @@ -84,8 +84,10 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifyBLS(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifyBLS(key, message, signature); + } } #[inline] @@ -139,8 +141,10 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifySecp256r1(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifySecp256r1(key, message, signature); + } } fn verify_bls_signature_share_managed( @@ -148,8 +152,10 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifyBLSSignatureShare(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifyBLSSignatureShare(key, message, signature); + } } fn verify_bls_aggregated_signature_managed( @@ -157,7 +163,9 @@ impl CryptoApiImpl for VmApiImpl { key: Self::ManagedBufferHandle, message: Self::ManagedBufferHandle, signature: Self::ManagedBufferHandle, - ) -> bool { - unsafe { managedVerifyBLSAggregatedSignature(key, message, signature) == 0 } + ) { + unsafe { + let _ = managedVerifyBLSAggregatedSignature(key, message, signature); + } } } From 0b43a3bafeb1e8dc3447e576291a66e23e77707b Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sun, 1 Sep 2024 02:34:06 +0300 Subject: [PATCH 52/52] scenario fmt --- .../basic-features/scenarios/managed_decimal.scen.json | 2 +- .../scenarios/managed_decimal_logarithm.scen.json | 2 +- .../scenarios/storage_mapper_get_at_address.scen.json | 2 +- .../scenarios/storage_mapper_get_at_address_extra_key.scen.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json index e19612ae29..b723c07b6d 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal.scen.json @@ -143,4 +143,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json index 065e92988c..193517275c 100644 --- a/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/managed_decimal_logarithm.scen.json @@ -107,4 +107,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json index 77ffdda1ee..2a0ff501a8 100644 --- a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address.scen.json @@ -372,4 +372,4 @@ } } ] -} \ No newline at end of file +} diff --git a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json index e124fd7e1a..d2802f41d2 100644 --- a/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json +++ b/contracts/feature-tests/basic-features/scenarios/storage_mapper_get_at_address_extra_key.scen.json @@ -87,4 +87,4 @@ } } ] -} \ No newline at end of file +}