diff --git a/Cargo.lock b/Cargo.lock index 973b51e9..32a6b797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -416,6 +416,7 @@ name = "cw-xcall-lib" version = "0.1.0" dependencies = [ "anyhow", + "common", "cosmwasm", "cosmwasm-schema", "cosmwasm-std", diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/Cargo.toml b/contracts/cosmwasm-vm/cw-xcall-lib/Cargo.toml index 48467885..0f85bac0 100644 --- a/contracts/cosmwasm-vm/cw-xcall-lib/Cargo.toml +++ b/contracts/cosmwasm-vm/cw-xcall-lib/Cargo.toml @@ -36,7 +36,7 @@ schemars = {workspace=true} serde = { workspace=true} thiserror = { workspace=true} debug_print={workspace=true} - +common = { git = "https://github.com/icon-project/IBC-Integration.git",branch="main" } [dev-dependencies] diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/lib.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/lib.rs index ae13fdb2..d32be794 100644 --- a/contracts/cosmwasm-vm/cw-xcall-lib/src/lib.rs +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/lib.rs @@ -1,5 +1,6 @@ pub mod dapp_msg; pub mod dapp_multi_msg; +pub mod message; pub mod network_address; pub mod xcall_connection_msg; pub mod xcall_msg; diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message.rs new file mode 100644 index 00000000..67061ea7 --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message.rs @@ -0,0 +1,36 @@ +use common::rlp::{self, Decodable, DecoderError, Encodable, RlpStream}; + +use super::msg_trait::IMessage; + +#[derive(Clone, Debug, PartialEq)] +pub struct CallMessage { + pub data: Vec, +} + +impl Encodable for CallMessage { + fn rlp_append(&self, stream: &mut RlpStream) { + stream.begin_list(1).append(&self.data); + } +} + +impl Decodable for CallMessage { + fn decode(rlp: &rlp::Rlp) -> Result { + Ok(Self { + data: rlp.val_at(0)?, + }) + } +} + +impl IMessage for CallMessage { + fn rollback(&self) -> Option> { + None + } + + fn data(&self) -> Vec { + self.data.clone() + } + + fn to_bytes(&self) -> Result, DecoderError> { + Ok(rlp::encode(self).to_vec()) + } +} diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message_rollback.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message_rollback.rs new file mode 100644 index 00000000..78222e8a --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message_rollback.rs @@ -0,0 +1,41 @@ +use common::rlp::{self, Decodable, DecoderError, Encodable, RlpStream}; + +use super::msg_trait::IMessage; + +#[derive(Clone, Debug, PartialEq)] +pub struct CallMessageWithRollback { + pub data: Vec, + pub rollback: Vec, +} + +impl Encodable for CallMessageWithRollback { + fn rlp_append(&self, stream: &mut RlpStream) { + stream + .begin_list(2) + .append(&self.data) + .append(&self.rollback); + } +} + +impl Decodable for CallMessageWithRollback { + fn decode(rlp: &rlp::Rlp) -> Result { + Ok(Self { + data: rlp.val_at(0)?, + rollback: rlp.val_at(1)?, + }) + } +} + +impl IMessage for CallMessageWithRollback { + fn rollback(&self) -> Option> { + Some(self.rollback.clone()) + } + + fn data(&self) -> Vec { + self.data.clone() + } + + fn to_bytes(&self) -> Result, DecoderError> { + Ok(rlp::encode(self).to_vec()) + } +} diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message/envelope.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/envelope.rs new file mode 100644 index 00000000..1f9ba610 --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/envelope.rs @@ -0,0 +1,117 @@ +use common::rlp::{self, Decodable, DecoderError, Encodable}; + +use super::{ + call_message::CallMessage, call_message_rollback::CallMessageWithRollback, msg_trait::IMessage, + msg_type::MessageType, AnyMessage, +}; +#[derive(Clone, Debug, PartialEq)] +pub struct Envelope { + pub message: AnyMessage, + pub sources: Vec, + pub destinations: Vec, +} + +impl Envelope { + pub fn new(msg: AnyMessage, sources: Vec, destinations: Vec) -> Self { + Self { + message: msg, + sources, + destinations, + } + } +} + +impl Encodable for Envelope { + fn rlp_append(&self, stream: &mut common::rlp::RlpStream) { + stream.begin_list(4); + stream.append(&Into::::into(self.message.msg_type().clone())); + stream.append(&self.message.to_bytes().unwrap()); + stream.begin_list(self.sources.len()); + for source in self.sources.iter() { + stream.append(source); + } + stream.begin_list(self.destinations.len()); + for dest in self.destinations.iter() { + stream.append(dest); + } + } +} + +impl Decodable for Envelope { + fn decode(rlp: &rlp::Rlp) -> Result { + let msg_int: u8 = rlp.val_at(0)?; + let msg_type = MessageType::from(msg_int); + let message_bytes: Vec = rlp.val_at(1)?; + let message = decode_message(msg_type, message_bytes)?; + + let sources = rlp.at(2)?; + let sources: Vec = sources.as_list()?; + let destinations = rlp.at(3)?; + let destinations: Vec = destinations.as_list()?; + + Ok(Envelope { + message, + sources, + destinations, + }) + } +} + +pub fn decode_message(msg_type: MessageType, bytes: Vec) -> Result { + match msg_type { + MessageType::CallMessage => { + let msg: CallMessage = rlp::decode(&bytes)?; + Ok(AnyMessage::CallMessage(msg)) + } + MessageType::CallMessageWithRollback => { + let msg: CallMessageWithRollback = rlp::decode(&bytes)?; + Ok(AnyMessage::CallMessageWithRollback(msg)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_encoding_decoding_envelope_call_message() { + // Create a sample Envelope + let message = AnyMessage::CallMessage(CallMessage { + data: vec![1, 2, 3], + }); + let sources = vec!["source1".to_string(), "source2".to_string()]; + let destinations = vec!["dest1".to_string(), "dest2".to_string()]; + let envelope = Envelope::new(message, sources, destinations); + let encoded_data = rlp::encode(&envelope).to_vec(); + + assert_eq!( + "e50185c483010203d087736f757263653187736f7572636532cc856465737431856465737432", + hex::encode(&encoded_data) + ); + let decoded: Envelope = rlp::decode(&encoded_data).unwrap(); + + assert_eq!(envelope, decoded); + } + + #[test] + fn test_encoding_decoding_envelope_call_message_rollback() { + // Create a sample Envelope + let message = AnyMessage::CallMessageWithRollback(CallMessageWithRollback { + data: vec![1, 2, 3], + rollback: vec![1, 2, 3], + }); + let sources = vec!["source1".to_string(), "source2".to_string()]; + let destinations = vec!["dest1".to_string(), "dest2".to_string()]; + let envelope = Envelope::new(message, sources, destinations); + let encoded_data = rlp::encode(&envelope).to_vec(); + + assert_eq!( + "e90289c88301020383010203d087736f757263653187736f7572636532cc856465737431856465737432", + hex::encode(&encoded_data) + ); + let decoded: Envelope = rlp::decode(&encoded_data).unwrap(); + + assert_eq!(envelope, decoded); + } +} diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message/mod.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/mod.rs new file mode 100644 index 00000000..bf8f215c --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/mod.rs @@ -0,0 +1,49 @@ +use common::rlp::DecoderError; + +use self::{ + call_message::CallMessage, call_message_rollback::CallMessageWithRollback, msg_trait::IMessage, + msg_type::MessageType, +}; + +pub mod call_message; +pub mod call_message_rollback; +pub mod envelope; +pub mod msg_trait; +pub mod msg_type; +#[derive(Clone, Debug, PartialEq)] +pub enum AnyMessage { + CallMessage(CallMessage), + CallMessageWithRollback(CallMessageWithRollback), +} + +impl IMessage for AnyMessage { + fn rollback(&self) -> Option> { + match self { + AnyMessage::CallMessage(m) => m.rollback(), + AnyMessage::CallMessageWithRollback(m) => m.rollback(), + } + } + + fn data(&self) -> Vec { + match self { + AnyMessage::CallMessage(m) => m.data(), + AnyMessage::CallMessageWithRollback(m) => m.data(), + } + } + + fn to_bytes(&self) -> Result, DecoderError> { + match self { + AnyMessage::CallMessage(m) => m.to_bytes(), + AnyMessage::CallMessageWithRollback(m) => m.to_bytes(), + } + } +} + +impl AnyMessage { + pub fn msg_type(&self) -> &MessageType { + match self { + AnyMessage::CallMessage(_m) => &MessageType::CallMessage, + AnyMessage::CallMessageWithRollback(_m) => &MessageType::CallMessageWithRollback, + } + } +} diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_trait.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_trait.rs new file mode 100644 index 00000000..5f89edc0 --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_trait.rs @@ -0,0 +1,8 @@ +use common::rlp::DecoderError; + +pub trait IMessage: Clone { + fn rollback(&self) -> Option>; + fn data(&self) -> Vec; + + fn to_bytes(&self) -> Result, DecoderError>; +} diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_type.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_type.rs new file mode 100644 index 00000000..2d59c3b7 --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_type.rs @@ -0,0 +1,35 @@ +use serde::Serialize; + +#[derive(Clone, Debug, Serialize, serde::Deserialize, PartialEq, Eq)] +pub enum MessageType { + CallMessage = 1, + CallMessageWithRollback = 2, +} + +impl From for u8 { + fn from(val: MessageType) -> Self { + match val { + MessageType::CallMessage => 1, + MessageType::CallMessageWithRollback => 2, + } + } +} + +impl From for MessageType { + fn from(value: u8) -> Self { + match value { + 1 => MessageType::CallMessage, + 2 => MessageType::CallMessageWithRollback, + _ => panic!("unsupported message type"), + } + } +} + +impl MessageType { + pub fn as_int(&self) -> u8 { + self.clone().into() + } + pub fn from_int(val: u8) -> Self { + MessageType::from(val) + } +} diff --git a/contracts/cosmwasm-vm/cw-xcall-lib/src/message_types.rs b/contracts/cosmwasm-vm/cw-xcall-lib/src/message_types.rs new file mode 100644 index 00000000..d91a78d8 --- /dev/null +++ b/contracts/cosmwasm-vm/cw-xcall-lib/src/message_types.rs @@ -0,0 +1,17 @@ +use common::rlp::Encodable; +use common::rlp::Decodable; + + +pub struct Message { + msg_type:MessageType, + data:Vec, +} + + +pub struct MessageWithRollback{ + msg_type:MessageType, + data:Vec, + rollback:Vec, +} + + diff --git a/contracts/cosmwasm-vm/cw-xcall/src/assertion.rs b/contracts/cosmwasm-vm/cw-xcall/src/assertion.rs index 2e608cde..f992acf1 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/assertion.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/assertion.rs @@ -200,6 +200,6 @@ impl<'a> CwCallService<'a> { /// `querier` object to get information about the contract at the given `address`. If the query is /// successful, it returns `true`, indicating that the address is a valid contract. If the query fails, /// it returns false ` -fn is_contract(querier: QuerierWrapper, address: &Addr) -> bool { +pub fn is_contract(querier: QuerierWrapper, address: &Addr) -> bool { querier.query_wasm_contract_info(address).is_ok() } diff --git a/contracts/cosmwasm-vm/cw-xcall/src/execute_call.rs b/contracts/cosmwasm-vm/cw-xcall/src/execute_call.rs index 41536e64..40b69f99 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/execute_call.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/execute_call.rs @@ -7,7 +7,7 @@ use crate::{ state::{CwCallService, EXECUTE_CALL_ID}, types::{ message::CSMessage, - response::{CSMessageResponse, CallServiceResponseType}, + result::{CSMessageResult, CallServiceResponseType}, }, }; @@ -82,7 +82,7 @@ impl<'a> CwCallService<'a> { cosmwasm_std::SubMsgResult::Ok(_res) => { let code = CallServiceResponseType::CallServiceResponseSuccess.into(); - let message_response = CSMessageResponse::new( + let message_response = CSMessageResult::new( request.sequence_no(), CallServiceResponseType::CallServiceResponseSuccess, ); @@ -92,14 +92,14 @@ impl<'a> CwCallService<'a> { cosmwasm_std::SubMsgResult::Err(err) => { let code = CallServiceResponseType::CallServiceResponseFailure; let error_message = format!("CallService Reverted : {err}"); - let message_response = CSMessageResponse::new(request.sequence_no(), code.clone()); + let message_response = CSMessageResult::new(request.sequence_no(), code.clone()); let event = event_call_executed(req_id, code.into(), &error_message); (message_response, event) } }; let mut submsgs: Vec = vec![]; let sn: i64 = -(request.sequence_no() as i64); - if request.rollback() { + if request.need_response() { let message: CSMessage = response.into(); let mut reply_address = request.protocols().clone(); let from = request.from().clone(); diff --git a/contracts/cosmwasm-vm/cw-xcall/src/handle_call_message.rs b/contracts/cosmwasm-vm/cw-xcall/src/handle_call_message.rs index ade3e6f3..cacc51ae 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/handle_call_message.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/handle_call_message.rs @@ -18,11 +18,11 @@ impl<'a> CwCallService<'a> { let call_service_message: CSMessage = CSMessage::try_from(message)?; match call_service_message.message_type() { - CallServiceMessageType::CallServiceRequest => { + CSMessageType::CSMessageRequest => { self.handle_request(deps, info, from_nid, call_service_message.payload()) } - CallServiceMessageType::CallServiceResponse => { - self.handle_response(deps, info, call_service_message.payload()) + CSMessageType::CSMessageResult => { + self.handle_result(deps, info, call_service_message.payload()) } } } @@ -68,7 +68,7 @@ impl<'a> CwCallService<'a> { request.from().clone(), request.to().clone(), request.sequence_no(), - request.rollback(), + request.msg_type(), keccak256(request.data().unwrap()).to_vec(), request.protocols().clone(), ); @@ -88,13 +88,13 @@ impl<'a> CwCallService<'a> { .add_event(event)) } - pub fn handle_response( + pub fn handle_result( &self, deps: DepsMut, info: MessageInfo, data: &[u8], ) -> Result { - let message: CSMessageResponse = rlp::decode(data).unwrap(); + let message: CSMessageResult = rlp::decode(data).unwrap(); let response_sequence_no = message.sequence_no(); @@ -194,7 +194,7 @@ impl<'a> CwCallService<'a> { info: MessageInfo, sn: u128, ) -> Result { - let msg = CSMessageResponse::new(sn, CallServiceResponseType::CallServiceResponseFailure); - self.handle_response(deps, info, &rlp::encode(&msg)) + let msg = CSMessageResult::new(sn, CallServiceResponseType::CallServiceResponseFailure); + self.handle_result(deps, info, &rlp::encode(&msg)) } } diff --git a/contracts/cosmwasm-vm/cw-xcall/src/lib.rs b/contracts/cosmwasm-vm/cw-xcall/src/lib.rs index 457df968..b3554e3c 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/lib.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/lib.rs @@ -26,9 +26,9 @@ use crate::{ state::{CwCallService, EXECUTE_CALL_ID}, types::{ call_request::CallRequest, - message::{CSMessage, CallServiceMessageType}, + message::{CSMessage, CSMessageType}, request::CSMessageRequest, - response::{CSMessageResponse, CallServiceResponseType}, + result::{CSMessageResult, CallServiceResponseType}, storage_keys::StorageKey, }, }; diff --git a/contracts/cosmwasm-vm/cw-xcall/src/send_call_message.rs b/contracts/cosmwasm-vm/cw-xcall/src/send_call_message.rs index 9f888003..25b8849d 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/send_call_message.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/send_call_message.rs @@ -1,7 +1,12 @@ use cosmwasm_std::{coins, BankMsg}; +use cw_xcall_lib::message::call_message::CallMessage; +use cw_xcall_lib::message::msg_trait::IMessage; + +use cw_xcall_lib::message::AnyMessage; +use cw_xcall_lib::message::{call_message_rollback::CallMessageWithRollback, envelope::Envelope}; use cw_xcall_lib::network_address::NetworkAddress; -use crate::types::LOG_PREFIX; +use crate::{assertion::is_contract, types::LOG_PREFIX}; use super::*; @@ -17,24 +22,50 @@ impl<'a> CwCallService<'a> { sources: Vec, destinations: Vec, ) -> Result { - let caller = info.sender; - let config = self.get_config(deps.as_ref().storage)?; - let nid = config.network_id; - - self.ensure_caller_is_contract_and_rollback_is_null(deps.as_ref(), &caller, &rollback)?; - - let need_response = rollback.is_some(); - - let rollback_data = match rollback { - Some(data) => data, - None => vec![], + let msg = if rollback.is_some() { + AnyMessage::CallMessageWithRollback(CallMessageWithRollback { + data, + rollback: rollback.unwrap(), + }) + } else { + AnyMessage::CallMessage(CallMessage { data }) }; + let envelope = Envelope::new(msg, sources, destinations); + self.send_call(deps, info, to, envelope) + } - self.ensure_rollback_length(&rollback_data)?; - println!("{LOG_PREFIX} Packet Validated"); + pub fn validate_payload( + &self, + deps: Deps, + caller: &Addr, + envelope: &Envelope, + ) -> Result<(), ContractError> { + match &envelope.message { + AnyMessage::CallMessage(_m) => Ok(()), + AnyMessage::CallMessageWithRollback(m) => { + if !is_contract(deps.querier, caller) { + return Err(ContractError::RollbackNotPossible); + } + self.ensure_rollback_length(&m.rollback().unwrap())?; + Ok(()) + } + } + } + + pub fn send_call( + &self, + deps: DepsMut, + info: MessageInfo, + to: NetworkAddress, + envelope: Envelope, + ) -> Result { + let caller = info.sender.clone(); + let config = self.get_config(deps.as_ref().storage)?; + let nid = config.network_id; + self.validate_payload(deps.as_ref(), &caller, &envelope)?; let sequence_no = self.get_next_sn(deps.storage)?; - let mut confirmed_sources = sources.clone(); + let mut confirmed_sources = envelope.sources.clone(); let from = NetworkAddress::new(&nid, caller.as_ref()); if confirmed_sources.is_empty() { @@ -42,22 +73,29 @@ impl<'a> CwCallService<'a> { confirmed_sources = vec![default.to_string()] } - if need_response { - let request = - CallRequest::new(caller.clone(), to.clone(), sources, rollback_data, false); + if envelope.message.rollback().is_some() { + let rollback_data = envelope.message.rollback().unwrap(); + let request = CallRequest::new( + caller.clone(), + to.clone(), + envelope.sources, + rollback_data, + false, + ); self.store_call_request(deps.storage, sequence_no, &request)?; } - let call_request = CSMessageRequest::new( from, to.account(), sequence_no, - need_response, - data.to_vec(), - destinations, + envelope.message.msg_type().clone(), + envelope.message.data(), + envelope.destinations, ); + let need_response = call_request.need_response(); + let message: CSMessage = call_request.into(); let sn: i64 = if need_response { sequence_no as i64 } else { 0 }; let mut total_spent = 0_u128; diff --git a/contracts/cosmwasm-vm/cw-xcall/src/types/message.rs b/contracts/cosmwasm-vm/cw-xcall/src/types/message.rs index 1ab718bf..0a6d5864 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/types/message.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/types/message.rs @@ -1,26 +1,26 @@ use super::*; #[cw_serde] -pub enum CallServiceMessageType { - CallServiceRequest = 1, - CallServiceResponse, +pub enum CSMessageType { + CSMessageRequest = 1, + CSMessageResult, } #[cw_serde] pub struct CSMessage { - pub message_type: CallServiceMessageType, + pub message_type: CSMessageType, pub payload: Vec, } impl CSMessage { - pub fn new(message_type: CallServiceMessageType, payload: Vec) -> Self { + pub fn new(message_type: CSMessageType, payload: Vec) -> Self { Self { message_type, payload: payload.to_vec(), } } - pub fn message_type(&self) -> &CallServiceMessageType { + pub fn message_type(&self) -> &CSMessageType { &self.message_type } pub fn payload(&self) -> &[u8] { @@ -31,8 +31,8 @@ impl CSMessage { impl Encodable for CSMessage { fn rlp_append(&self, stream: &mut rlp::RlpStream) { let msg_type: u8 = match self.message_type { - CallServiceMessageType::CallServiceRequest => 1, - CallServiceMessageType::CallServiceResponse => 2, + CSMessageType::CSMessageRequest => 1, + CSMessageType::CSMessageResult => 2, }; stream.begin_list(2).append(&msg_type).append(&self.payload); } @@ -44,8 +44,8 @@ impl Decodable for CSMessage { Ok(Self { message_type: match msg_type { - 1 => Ok(CallServiceMessageType::CallServiceRequest), - 2 => Ok(CallServiceMessageType::CallServiceResponse), + 1 => Ok(CSMessageType::CSMessageRequest), + 2 => Ok(CSMessageType::CSMessageResult), _ => Err(rlp::DecoderError::Custom("Invalid type")), }?, payload: rlp.val_at(1)?, @@ -56,16 +56,16 @@ impl Decodable for CSMessage { impl From for CSMessage { fn from(value: CSMessageRequest) -> Self { Self { - message_type: CallServiceMessageType::CallServiceRequest, + message_type: CSMessageType::CSMessageRequest, payload: rlp::encode(&value).to_vec(), } } } -impl From for CSMessage { - fn from(value: CSMessageResponse) -> Self { +impl From for CSMessage { + fn from(value: CSMessageResult) -> Self { Self { - message_type: CallServiceMessageType::CallServiceResponse, + message_type: CSMessageType::CSMessageResult, payload: rlp::encode(&value).to_vec(), } } @@ -119,18 +119,12 @@ mod tests { #[test] fn test_csmessage_encoding() { let data = hex::decode("7465737431").unwrap(); - let message = CSMessage::new( - super::CallServiceMessageType::CallServiceRequest, - data.clone(), - ); + let message = CSMessage::new(super::CSMessageType::CSMessageRequest, data.clone()); let encoded = rlp::encode(&message); assert_eq!("c701857465737431", hex::encode(encoded)); - let message = CSMessage::new( - crate::types::message::CallServiceMessageType::CallServiceResponse, - data, - ); + let message = CSMessage::new(crate::types::message::CSMessageType::CSMessageResult, data); let encoded = rlp::encode(&message); assert_eq!("c702857465737431", hex::encode(encoded)); } diff --git a/contracts/cosmwasm-vm/cw-xcall/src/types/mod.rs b/contracts/cosmwasm-vm/cw-xcall/src/types/mod.rs index 4f2d8210..be99eac4 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/types/mod.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/types/mod.rs @@ -2,7 +2,7 @@ pub mod call_request; pub mod config; pub mod message; pub mod request; -pub mod response; +pub mod result; pub mod storage_keys; pub const LOG_PREFIX: &str = "[xcall_app]:"; @@ -13,4 +13,4 @@ use common::rlp::{Decodable, Encodable}; use cosmwasm_schema::cw_serde; use cosmwasm_std::{to_binary, Binary}; use request::CSMessageRequest; -use response::CSMessageResponse; +use result::CSMessageResult; diff --git a/contracts/cosmwasm-vm/cw-xcall/src/types/request.rs b/contracts/cosmwasm-vm/cw-xcall/src/types/request.rs index 6cdf06ab..155af4bf 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/types/request.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/types/request.rs @@ -1,7 +1,7 @@ use super::*; use common::rlp::Nullable; use cosmwasm_std::Addr; -use cw_xcall_lib::network_address::NetworkAddress; +use cw_xcall_lib::{message::msg_type::MessageType, network_address::NetworkAddress}; use serde::{Deserialize, Serialize}; use std::str::FromStr; @@ -11,7 +11,7 @@ pub struct CSMessageRequest { to: Addr, sequence_no: u128, protocols: Vec, - rollback: bool, + msg_type: MessageType, data: Nullable>, } @@ -20,7 +20,7 @@ impl CSMessageRequest { from: NetworkAddress, to: Addr, sequence_no: u128, - rollback: bool, + msg_type: MessageType, data: Vec, protocols: Vec, ) -> Self { @@ -32,7 +32,7 @@ impl CSMessageRequest { from, to, sequence_no, - rollback, + msg_type, data: Nullable::new(data_bytes), protocols, } @@ -50,8 +50,12 @@ impl CSMessageRequest { self.sequence_no } - pub fn rollback(&self) -> bool { - self.rollback + pub fn msg_type(&self) -> MessageType { + self.msg_type.clone() + } + + pub fn need_response(&self) -> bool { + self.msg_type == MessageType::CallMessageWithRollback } pub fn data(&self) -> Result<&[u8], ContractError> { @@ -74,7 +78,7 @@ impl Encodable for CSMessageRequest { stream.append(&self.from.to_string()); stream.append(&self.to.to_string()); stream.append(&self.sequence_no); - stream.append(&self.rollback); + stream.append(&self.msg_type.as_int()); stream.append(&self.data); stream.begin_list(self.protocols.len()); for protocol in self.protocols.iter() { @@ -89,12 +93,13 @@ impl Decodable for CSMessageRequest { let list: Vec = rlp_protocols.as_list()?; let str_from: String = rlp.val_at(0)?; let to_str: String = rlp.val_at(1)?; + let msg_type_int: u8 = rlp.val_at(3)?; Ok(Self { from: NetworkAddress::from_str(&str_from) .map_err(|_e| rlp::DecoderError::RlpInvalidLength)?, to: Addr::unchecked(to_str), sequence_no: rlp.val_at(2)?, - rollback: rlp.val_at(3)?, + msg_type: MessageType::from_int(msg_type_int), data: rlp.val_at(4)?, protocols: list, }) @@ -129,28 +134,28 @@ mod tests { from: 0x1.ETH/0xa to: cx0000000000000000000000000000000000000102 sn: 21 - rollback: false + messageType: 1 data: 74657374 protocol: [] - RLP: F83F8B3078312E4554482F307861AA63783030303030303030303030303030303030303030303030303030303030303030303030303031303215008474657374C0 + RLP: f83f8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215018474657374c0 CSMessageRequest from: 0x1.ETH/0xa to: cx0000000000000000000000000000000000000102 sn: 21 - rollback: false + messageType: 1 data: 74657374 protocol: [abc, cde, efg] - RLP: F84B8B3078312E4554482F307861AA63783030303030303030303030303030303030303030303030303030303030303030303030303031303215008474657374CC836162638363646583656667 + RLP: f84b8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215018474657374cc836162638363646583656667 CSMessageRequest from: 0x1.ETH/0xa to: cx0000000000000000000000000000000000000102 sn: 21 - rollback: true + messageType: 2 data: 74657374 protocol: [abc, cde, efg] - RLP: F84B8B3078312E4554482F307861AA63783030303030303030303030303030303030303030303030303030303030303030303030303031303215018474657374CC836162638363646583656667 + RLP: f84b8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215028474657374cc836162638363646583656667 */ @@ -162,6 +167,7 @@ mod tests { use cw_xcall_lib::network_address::NetworkAddress; use super::CSMessageRequest; + use cw_xcall_lib::message::msg_type::MessageType; #[test] fn test_csmessage_request_encoding() { @@ -170,36 +176,39 @@ mod tests { NetworkAddress::from_str("0x1.ETH/0xa").unwrap(), Addr::unchecked("cx0000000000000000000000000000000000000102"), 21, - false, + MessageType::CallMessage, data.clone(), vec![], ); let encoded = rlp::encode(&msg); - assert_eq!("f83f8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215008474657374c0",hex::encode(encoded)); + + assert_eq!("f83f8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215018474657374c0",hex::encode(encoded)); let msg = CSMessageRequest::new( NetworkAddress::from_str("0x1.ETH/0xa").unwrap(), Addr::unchecked("cx0000000000000000000000000000000000000102"), 21, - false, + MessageType::CallMessage, data.clone(), vec!["abc".to_string(), "cde".to_string(), "efg".to_string()], ); let encoded = rlp::encode(&msg); - assert_eq!("f84b8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215008474657374cc836162638363646583656667",hex::encode(encoded)); + + assert_eq!("f84b8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215018474657374cc836162638363646583656667",hex::encode(encoded)); let msg = CSMessageRequest::new( NetworkAddress::from_str("0x1.ETH/0xa").unwrap(), Addr::unchecked("cx0000000000000000000000000000000000000102"), 21, - true, + MessageType::CallMessageWithRollback, data, vec!["abc".to_string(), "cde".to_string(), "efg".to_string()], ); let encoded = rlp::encode(&msg); - assert_eq!("f84b8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215018474657374cc836162638363646583656667",hex::encode(encoded)); + + assert_eq!("f84b8b3078312e4554482f307861aa63783030303030303030303030303030303030303030303030303030303030303030303030303031303215028474657374cc836162638363646583656667",hex::encode(encoded)); } } diff --git a/contracts/cosmwasm-vm/cw-xcall/src/types/response.rs b/contracts/cosmwasm-vm/cw-xcall/src/types/result.rs similarity index 86% rename from contracts/cosmwasm-vm/cw-xcall/src/types/response.rs rename to contracts/cosmwasm-vm/cw-xcall/src/types/result.rs index e52addab..dfb3d63c 100644 --- a/contracts/cosmwasm-vm/cw-xcall/src/types/response.rs +++ b/contracts/cosmwasm-vm/cw-xcall/src/types/result.rs @@ -25,12 +25,12 @@ impl TryFrom for CallServiceResponseType { } #[cw_serde] -pub struct CSMessageResponse { +pub struct CSMessageResult { sequence_no: u128, response_code: CallServiceResponseType, } -impl CSMessageResponse { +impl CSMessageResult { pub fn new(sequence_no: u128, response_code: CallServiceResponseType) -> Self { Self { sequence_no, @@ -52,7 +52,7 @@ impl CSMessageResponse { } } -impl Encodable for CSMessageResponse { +impl Encodable for CSMessageResult { fn rlp_append(&self, stream: &mut rlp::RlpStream) { let code: u8 = self.response_code.clone().into(); @@ -63,7 +63,7 @@ impl Encodable for CSMessageResponse { } } -impl Decodable for CSMessageResponse { +impl Decodable for CSMessageResult { fn decode(rlp: &rlp::Rlp) -> Result { let code: u8 = rlp.val_at(1)?; @@ -74,7 +74,7 @@ impl Decodable for CSMessageResponse { } } -impl TryFrom<&Vec> for CSMessageResponse { +impl TryFrom<&Vec> for CSMessageResult { type Error = ContractError; fn try_from(value: &Vec) -> Result { let rlp = rlp::Rlp::new(value as &[u8]); @@ -84,7 +84,7 @@ impl TryFrom<&Vec> for CSMessageResponse { } } -impl TryFrom<&[u8]> for CSMessageResponse { +impl TryFrom<&[u8]> for CSMessageResult { type Error = ContractError; fn try_from(value: &[u8]) -> Result { let rlp = rlp::Rlp::new(value); @@ -112,18 +112,18 @@ mod tests { use common::rlp; - use super::{CSMessageResponse, CallServiceResponseType}; + use super::{CSMessageResult, CallServiceResponseType}; #[test] fn test_cs_message_response_encoding() { let cs_response = - CSMessageResponse::new(1, CallServiceResponseType::CallServiceResponseSuccess); + CSMessageResult::new(1, CallServiceResponseType::CallServiceResponseSuccess); let encoded = rlp::encode(&cs_response); assert_eq!("c20101", hex::encode(encoded)); let cs_response = - CSMessageResponse::new(2, CallServiceResponseType::CallServiceResponseFailure); + CSMessageResult::new(2, CallServiceResponseType::CallServiceResponseFailure); let encoded = rlp::encode(&cs_response); assert_eq!("c20200", hex::encode(encoded)); diff --git a/contracts/cosmwasm-vm/cw-xcall/tests/test_call_message.rs b/contracts/cosmwasm-vm/cw-xcall/tests/test_call_message.rs index 068e3c24..747d5901 100644 --- a/contracts/cosmwasm-vm/cw-xcall/tests/test_call_message.rs +++ b/contracts/cosmwasm-vm/cw-xcall/tests/test_call_message.rs @@ -1,6 +1,6 @@ mod account; mod setup; -use std::{collections::HashMap, vec}; +use std::{collections::HashMap, str::FromStr, vec}; use crate::account::*; use cosmwasm_std::{ @@ -34,6 +34,20 @@ fn send_packet_by_non_contract_and_rollback_data_is_not_null() { }, ) .unwrap(); + contract + .set_admin( + mock_deps.as_mut().storage, + Addr::unchecked(alice().to_string()), + ) + .unwrap(); + contract + .set_default_connection( + mock_deps.as_mut(), + mock_info.clone(), + NetId::from_str("nid").unwrap(), + Addr::unchecked("defaultconn".to_string()), + ) + .unwrap(); contract .send_call_message( diff --git a/contracts/cosmwasm-vm/cw-xcall/tests/test_handle_call_message.rs b/contracts/cosmwasm-vm/cw-xcall/tests/test_handle_call_message.rs index 298b114a..19404dff 100644 --- a/contracts/cosmwasm-vm/cw-xcall/tests/test_handle_call_message.rs +++ b/contracts/cosmwasm-vm/cw-xcall/tests/test_handle_call_message.rs @@ -9,7 +9,7 @@ use cw_xcall::{ state::{CwCallService, EXECUTE_CALL_ID}, types::{call_request::CallRequest, request::CSMessageRequest}, }; -use cw_xcall_lib::network_address::NetworkAddress; +use cw_xcall_lib::{message::msg_type::MessageType, network_address::NetworkAddress}; mod account; mod setup; use crate::account::alice; @@ -42,7 +42,7 @@ fn test_execute_call_with_wrong_data() { NetworkAddress::new("nid", "mockaddress"), Addr::unchecked("88bd05442686be0a5df7da33b6f1089ebfea3769b19dbb2477fe0cd6e0f123t7"), 123, - false, + MessageType::CallMessage, keccak256(&[104, 106, 108, 108, 111]).to_vec(), vec![], ); @@ -67,7 +67,7 @@ fn test_execute_call_having_request_id_without_rollback() { NetworkAddress::new("nid", "mockaddress"), Addr::unchecked("88bd05442686be0a5df7da33b6f1089ebfea3769b19dbb2477fe0cd6e0f123t7"), 123, - false, + MessageType::CallMessage, keccak256(&data).to_vec(), vec![], ); @@ -119,7 +119,7 @@ fn test_successful_reply_message() { NetworkAddress::new("nid", "mockaddress"), Addr::unchecked("88bd05442686be0a5df7da33b6f1089ebfea3769b19dbb2477fe0cd6e0f123t7"), 123, - false, + MessageType::CallMessage, vec![], vec![], ); @@ -154,7 +154,7 @@ fn test_failed_reply_message() { NetworkAddress::new("nid", "mockaddress"), Addr::unchecked("88bd05442686be0a5df7da33b6f1089ebfea3769b19dbb2477fe0cd6e0f123t7"), 123, - false, + MessageType::CallMessage, vec![], vec![], ); diff --git a/contracts/javascore/xcall/src/main/java/foundation/icon/xcall/CallServiceImpl.java b/contracts/javascore/xcall/src/main/java/foundation/icon/xcall/CallServiceImpl.java index d0b17be2..94f9ff7b 100644 --- a/contracts/javascore/xcall/src/main/java/foundation/icon/xcall/CallServiceImpl.java +++ b/contracts/javascore/xcall/src/main/java/foundation/icon/xcall/CallServiceImpl.java @@ -133,7 +133,6 @@ public BigInteger sendCall(String _to, byte[] _data) { return sn; } - @Override @Payable @External public BigInteger sendCallMessage(String _to,