Skip to content

Commit

Permalink
unified syntax - tx hash in blackbox/whitebox tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Sep 20, 2024
1 parent b72c23d commit 69d09a5
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 38 deletions.
42 changes: 42 additions & 0 deletions contracts/feature-tests/scenario-tester/tests/st_blackbox_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,45 @@ fn set_state_test() {
.balance(600)
.esdt_balance(TOKEN_ID, 60);
}

#[test]
fn st_blackbox_tx_hash() {
let mut world = world();

world
.account(OWNER_ADDRESS)
.nonce(1)
.balance(100)
.account(OTHER_ADDRESS)
.nonce(2)
.balance(300)
.esdt_balance(TOKEN_ID, 500)
.commit();

let (new_address, tx_hash) = world
.tx()
.from(OWNER_ADDRESS)
.typed(scenario_tester_proxy::ScenarioTesterProxy)
.init(5u32)
.code(CODE_PATH)
.new_address(ST_ADDRESS)
.tx_hash([11u8; 32])
.returns(ReturnsNewAddress)
.returns(ReturnsTxHash)
.run();

assert_eq!(new_address, ST_ADDRESS.to_address());
assert_eq!(tx_hash.as_array(), &[11u8; 32]);

let tx_hash = world
.tx()
.from(OWNER_ADDRESS)
.to(ST_ADDRESS)
.typed(scenario_tester_proxy::ScenarioTesterProxy)
.add(1u32)
.tx_hash([22u8; 32])
.returns(ReturnsTxHash)
.run();

assert_eq!(tx_hash.as_array(), &[22u8; 32]);
}
33 changes: 33 additions & 0 deletions contracts/feature-tests/scenario-tester/tests/st_whitebox_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,36 @@ fn st_whitebox() {
.check_account(SCENARIO_TESTER)
.check_storage("str:sum", "8");
}

#[test]
fn st_whitebox_tx_hash() {
let mut world = world();

world.account(OWNER).nonce(1);

let (new_address, tx_hash) = world
.tx()
.from(OWNER)
.raw_deploy()
.code(ST_PATH_EXPR)
.new_address(SCENARIO_TESTER)
.tx_hash([11u8; 32])
.returns(ReturnsNewBech32Address)
.returns(ReturnsTxHash)
.whitebox(scenario_tester::contract_obj, |sc| {
sc.init(BigUint::from(5u64));
});

assert_eq!(new_address.to_address(), SCENARIO_TESTER.to_address());
assert_eq!(tx_hash.as_array(), &[11u8; 32]);

let tx_hash = world
.tx()
.from(OWNER)
.to(SCENARIO_TESTER)
.tx_hash([22u8; 32])
.returns(ReturnsTxHash)
.whitebox(scenario_tester::contract_obj, |sc| sc.add(3u32.into()));

assert_eq!(tx_hash.as_array(), &[22u8; 32]);
}
6 changes: 3 additions & 3 deletions framework/base/src/types/interaction/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,11 +908,11 @@ where
impl<Env, From, To, Payment, Gas, Data, RH> Tx<Env, From, To, Payment, Gas, Data, RH>
where
Env: TxEnvWithTxHash,
From: TxFromSpecified<Env>,
From: TxFrom<Env>,
To: TxTo<Env>,
Payment: TxPaymentEgldOnly<Env>,
Payment: TxPayment<Env>,
Gas: TxGas<Env>,
Data: TxDataFunctionCall<Env>,
Data: TxData<Env>,
RH: TxResultHandler<Env>,
{
/// Sets the mock transaction hash to be used in a test.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use multiversx_chain_vm::types::H256;
use multiversx_sc::types::RHListItemExec;

use crate::{
Expand All @@ -11,14 +12,14 @@ impl<Env, Original> RHListItem<Env, Original> for ReturnsTxHash
where
Env: TxEnv,
{
type Returns = String;
type Returns = H256;
}

impl<Env, Original> RHListItemExec<TxResponse, Env, Original> for ReturnsTxHash
where
Env: TxEnv,
{
fn item_process_result(self, raw_result: &TxResponse) -> Self::Returns {
raw_result.tx_hash.clone()
raw_result.tx_hash.clone().expect("missing tx hash")
}
}
24 changes: 3 additions & 21 deletions framework/scenario/src/facade/world_tx/scenario_tx_whitebox.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use core::str;

use crate::debug_executor::contract_instance_wrapped_execution;
use crate::scenario::tx_to_step::TxToQueryStep;
use crate::{
Expand Down Expand Up @@ -57,6 +55,7 @@ where
let contract_obj = contract_obj_builder();

let mut step_wrapper = self.tx_to_step();
step_wrapper.step.explicit_tx_hash = core::mem::take(&mut step_wrapper.env.data.tx_hash);
let (new_address, tx_result) = step_wrapper
.env
.world
Expand All @@ -70,15 +69,6 @@ where
});

let mut response = TxResponse::from_tx_result(tx_result);
if let Some(tx_hash) = &step_wrapper.env.data.tx_hash {
let tx_hash_bytes = tx_hash.as_bytes();
response.tx_hash = str::from_utf8(tx_hash_bytes)
.expect("tx hash not utf8 valid")
.to_string();
} else {
response.tx_hash = String::from("");
}

response.new_deployed_address = Some(new_address);
step_wrapper.step.save_response(response);
step_wrapper.process_result()
Expand Down Expand Up @@ -133,6 +123,7 @@ where
let contract_obj = contract_obj_builder();

let mut step_wrapper = self.tx_to_step();
step_wrapper.step.explicit_tx_hash = core::mem::take(&mut step_wrapper.env.data.tx_hash);

// 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() {
Expand All @@ -151,16 +142,7 @@ where
});
});

let mut response = TxResponse::from_tx_result(tx_result);
if let Some(tx_hash) = &step_wrapper.env.data.tx_hash {
let tx_hash_bytes = tx_hash.as_bytes();
response.tx_hash = str::from_utf8(tx_hash_bytes)
.expect("tx hash not utf8 valid")
.to_string();
} else {
response.tx_hash = String::from("");
}

let response = TxResponse::from_tx_result(tx_result);
step_wrapper.step.save_response(response);
step_wrapper.process_result()
}
Expand Down
3 changes: 2 additions & 1 deletion framework/scenario/src/scenario/model/step/sc_call_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,13 @@ impl ScCallStep {
.expect("SC call response not yet available")
}

pub fn save_response(&mut self, tx_response: TxResponse) {
pub fn save_response(&mut self, mut tx_response: TxResponse) {
if let Some(expect) = &mut self.expect {
if expect.build_from_response {
expect.update_from_response(&tx_response)
}
}
tx_response.tx_hash = self.explicit_tx_hash.as_ref().map(|vm_hash| vm_hash.as_array().into());
self.response = Some(tx_response);
}
}
Expand Down
7 changes: 4 additions & 3 deletions framework/scenario/src/scenario/model/step/sc_deploy_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,14 @@ impl ScDeployStep {
.expect("SC deploy response not yet available")
}

pub fn save_response(&mut self, response: TxResponse) {
pub fn save_response(&mut self, mut tx_response: TxResponse) {
if let Some(expect) = &mut self.expect {
if expect.build_from_response {
expect.update_from_response(&response)
expect.update_from_response(&tx_response)
}
}
self.response = Some(response);
tx_response.tx_hash = self.explicit_tx_hash.as_ref().map(|vm_hash| vm_hash.as_array().into());
self.response = Some(tx_response);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use multiversx_chain_vm::tx_mock::TxResult;
use multiversx_chain_vm::{tx_mock::TxResult, types::H256};
use multiversx_sc::types::Address;

use super::{Log, TxExpect, TxResponseStatus};
Expand All @@ -20,8 +20,8 @@ pub struct TxResponse {
pub gas: u64,
/// The refund of the transaction.
pub refund: u64,
/// The transaction hash
pub tx_hash: String,
/// The transaction hash, if available.
pub tx_hash: Option<H256>,
}

impl TxResponse {
Expand Down
14 changes: 9 additions & 5 deletions framework/snippets/src/network_response.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use multiversx_sc_scenario::{
imports::{Address, ESDTSystemSCAddress},
multiversx_chain_vm::crypto_functions::keccak256,
multiversx_chain_vm::{crypto_functions::keccak256, types::H256},
scenario_model::{Log, TxResponse, TxResponseStatus},
};
use multiversx_sdk::{
Expand All @@ -17,7 +17,7 @@ pub fn parse_tx_response(tx: TransactionOnNetwork) -> TxResponse {
if !tx_error.is_success() {
return TxResponse {
tx_error,
tx_hash: process_tx_hash(&tx).to_string(),
tx_hash: process_tx_hash(&tx),
..Default::default()
};
}
Expand Down Expand Up @@ -46,13 +46,17 @@ fn process_success(tx: &TransactionOnNetwork) -> TxResponse {
new_deployed_address: process_new_deployed_address(tx),
new_issued_token_identifier: process_new_issued_token_identifier(tx),
logs: process_logs(tx),
tx_hash: process_tx_hash(tx).to_string(),
tx_hash: process_tx_hash(tx),
..Default::default()
}
}

fn process_tx_hash(tx: &TransactionOnNetwork) -> &str {
tx.hash.as_deref().unwrap_or("")
fn process_tx_hash(tx: &TransactionOnNetwork) -> Option<H256> {
tx.hash.as_ref().map(|encoded_hash| {
let decoded = hex::decode(encoded_hash).expect("error decoding tx hash from hex");
assert_eq!(decoded.len(), 32);
H256::from_slice(&decoded)
})
}

fn process_out(tx: &TransactionOnNetwork) -> Vec<Vec<u8>> {
Expand Down

0 comments on commit 69d09a5

Please sign in to comment.