From 22f47deec6a073268dad53195138a18ef34cb158 Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 2 Aug 2023 12:01:19 +0200 Subject: [PATCH] add a test for receiving no token --- tests/src/vm_host_env/ibc.rs | 7 +++ tests/src/vm_host_env/mod.rs | 82 ++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/tests/src/vm_host_env/ibc.rs b/tests/src/vm_host_env/ibc.rs index 97d5f5e6f48..59edad54658 100644 --- a/tests/src/vm_host_env/ibc.rs +++ b/tests/src/vm_host_env/ibc.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use namada::ibc::applications::transfer::acknowledgement::TokenTransferAcknowledgement; use namada::ibc::applications::transfer::coin::PrefixedCoin; +use namada::ibc::applications::transfer::error::TokenTransferError; use namada::ibc::applications::transfer::msgs::transfer::MsgTransfer; use namada::ibc::applications::transfer::packet::PacketData; use namada::ibc::applications::transfer::VERSION; @@ -780,3 +781,9 @@ pub fn balance_key_with_ibc_prefix(denom: String, owner: &Address) -> Key { let ibc_token = ibc_token(denom); token::balance_key(&ibc_token, owner) } + +pub fn transfer_ack_with_error() -> TokenTransferAcknowledgement { + TokenTransferAcknowledgement::Error( + TokenTransferError::PacketDataDeserialization.to_string(), + ) +} diff --git a/tests/src/vm_host_env/mod.rs b/tests/src/vm_host_env/mod.rs index d39615b7b6d..483b886c210 100644 --- a/tests/src/vm_host_env/mod.rs +++ b/tests/src/vm_host_env/mod.rs @@ -18,6 +18,7 @@ pub mod vp; #[cfg(test)] mod tests { + use std::collections::BTreeSet; use std::panic; use itertools::Itertools; @@ -1332,6 +1333,87 @@ mod tests { assert_eq!(minted, Some(Amount::from_u64(100))); } + #[test] + fn test_ibc_receive_no_token() { + // The environment must be initialized first + tx_host_env::init(); + + // Set the initial state before starting transactions + let (token, receiver) = ibc::init_storage(); + let (client_id, _client_state, mut writes) = ibc::prepare_client(); + let (conn_id, conn_writes) = ibc::prepare_opened_connection(&client_id); + writes.extend(conn_writes); + let (port_id, channel_id, channel_writes) = + ibc::prepare_opened_channel(&conn_id, false); + writes.extend(channel_writes); + + writes.into_iter().for_each(|(key, val)| { + tx_host_env::with(|env| { + env.wl_storage + .storage + .write(&key, &val) + .expect("write error"); + }); + }); + + // packet with invalid data + let sequence = ibc::Sequence::from(1); + let mut packet = ibc::received_packet( + port_id.clone(), + channel_id.clone(), + sequence, + token.to_string(), + &receiver, + ); + packet.data = vec![0]; + + // Start a transaction to receive a packet + let msg = ibc::msg_packet_recv(packet); + let mut tx_data = vec![]; + msg.to_any().encode(&mut tx_data).expect("encoding failed"); + + let mut tx = Tx::new(TxType::Raw); + tx.set_code(Code::new(vec![])); + tx.set_data(Data::new(tx_data.clone())); + tx.add_section(Section::Signature(Signature::new( + vec![*tx.code_sechash(), *tx.data_sechash()], + &key::testing::keypair_1(), + ))); + // Receive the packet, but no token is received + tx_host_env::ibc::ibc_actions(tx::ctx()) + .execute(&tx_data) + .expect("receiving the token failed"); + + // Check if the transaction is valid + let env = tx_host_env::take(); + let result = ibc::validate_ibc_vp_from_tx(&env, &tx); + assert!(result.expect("validation failed unexpectedly")); + // Check if the ack has an error due to the invalid packet data + tx_host_env::set(env); + let ack_key = ibc_storage::ack_key(&port_id, &channel_id, sequence); + let ack = tx_host_env::with(|env| { + env.wl_storage + .read_bytes(&ack_key) + .expect("read error") + .unwrap() + }); + let expected_ack = + Hash::sha256(Vec::::from(ibc::transfer_ack_with_error())) + .to_vec(); + assert_eq!(ack, expected_ack); + // Check if only the ack and the receipt are added + let receipt_key = + ibc_storage::receipt_key(&port_id, &channel_id, sequence); + let changed_keys = tx_host_env::with(|env| { + env.wl_storage + .write_log + .verifiers_and_changed_keys(&BTreeSet::new()) + .1 + }); + let expected_changed_keys = BTreeSet::from([ack_key, receipt_key]); + assert_eq!(changed_keys, expected_changed_keys); + } + #[test] fn test_ibc_unescrow_token() { // The environment must be initialized first