Skip to content

Commit

Permalink
feat: multi message rust (#171)
Browse files Browse the repository at this point in the history
* feat: Add message types to xCall

* feat: add multi message

* fix: fix test

* refactor: csresponse to scresult

* refactor: csmessage type

* docs: Add new message strucute to xCall design doc

* refactor: rename result

* fix: fix test

* chore: cleanup

* test: add test for envelope encoding

* test: add envelope encoding test

* chore: fix lint

* feat: Add message types to xCall

* fix: remove should persist

* fix: remove duplicate merge

* fix: encode length

* fix: remove msg type

* test: fix tests

* fix: Revert change of rollback db name

Break out db paths into static String variables

* Update docs/adr/xcall.md

Co-authored-by: AntonAndell <[email protected]>

---------

Co-authored-by: AntonAndell <[email protected]>
  • Loading branch information
2 people authored and bishalbikram committed Oct 2, 2024
1 parent 7b2d95b commit f89db9d
Show file tree
Hide file tree
Showing 22 changed files with 457 additions and 98 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/cosmwasm-vm/cw-xcall-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,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]
Expand Down
1 change: 1 addition & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
36 changes: 36 additions & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/message/call_message.rs
Original file line number Diff line number Diff line change
@@ -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<u8>,
}

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<Self, rlp::DecoderError> {
Ok(Self {
data: rlp.val_at(0)?,
})
}
}

impl IMessage for CallMessage {
fn rollback(&self) -> Option<Vec<u8>> {
None
}

fn data(&self) -> Vec<u8> {
self.data.clone()
}

fn to_bytes(&self) -> Result<Vec<u8>, DecoderError> {
Ok(rlp::encode(self).to_vec())
}
}
Original file line number Diff line number Diff line change
@@ -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<u8>,
pub rollback: Vec<u8>,
}

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<Self, rlp::DecoderError> {
Ok(Self {
data: rlp.val_at(0)?,
rollback: rlp.val_at(1)?,
})
}
}

impl IMessage for CallMessageWithRollback {
fn rollback(&self) -> Option<Vec<u8>> {
Some(self.rollback.clone())
}

fn data(&self) -> Vec<u8> {
self.data.clone()
}

fn to_bytes(&self) -> Result<Vec<u8>, DecoderError> {
Ok(rlp::encode(self).to_vec())
}
}
117 changes: 117 additions & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/message/envelope.rs
Original file line number Diff line number Diff line change
@@ -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<String>,
pub destinations: Vec<String>,
}

impl Envelope {
pub fn new(msg: AnyMessage, sources: Vec<String>, destinations: Vec<String>) -> 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::<u8>::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<Self, rlp::DecoderError> {
let msg_int: u8 = rlp.val_at(0)?;
let msg_type = MessageType::from(msg_int);
let message_bytes: Vec<u8> = rlp.val_at(1)?;
let message = decode_message(msg_type, message_bytes)?;

let sources = rlp.at(2)?;
let sources: Vec<String> = sources.as_list()?;
let destinations = rlp.at(3)?;
let destinations: Vec<String> = destinations.as_list()?;

Ok(Envelope {
message,
sources,
destinations,
})
}
}

pub fn decode_message(msg_type: MessageType, bytes: Vec<u8>) -> Result<AnyMessage, DecoderError> {
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);
}
}
49 changes: 49 additions & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/message/mod.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<u8>> {
match self {
AnyMessage::CallMessage(m) => m.rollback(),
AnyMessage::CallMessageWithRollback(m) => m.rollback(),
}
}

fn data(&self) -> Vec<u8> {
match self {
AnyMessage::CallMessage(m) => m.data(),
AnyMessage::CallMessageWithRollback(m) => m.data(),
}
}

fn to_bytes(&self) -> Result<Vec<u8>, 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,
}
}
}
8 changes: 8 additions & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use common::rlp::DecoderError;

pub trait IMessage: Clone {
fn rollback(&self) -> Option<Vec<u8>>;
fn data(&self) -> Vec<u8>;

fn to_bytes(&self) -> Result<Vec<u8>, DecoderError>;
}
35 changes: 35 additions & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/message/msg_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use serde::Serialize;

#[derive(Clone, Debug, Serialize, serde::Deserialize, PartialEq, Eq)]
pub enum MessageType {
CallMessage = 1,
CallMessageWithRollback = 2,
}

impl From<MessageType> for u8 {
fn from(val: MessageType) -> Self {
match val {
MessageType::CallMessage => 1,
MessageType::CallMessageWithRollback => 2,
}
}
}

impl From<u8> 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)
}
}
17 changes: 17 additions & 0 deletions contracts/cosmwasm-vm/cw-xcall-lib/src/message_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use common::rlp::Encodable;
use common::rlp::Decodable;


pub struct Message {
msg_type:MessageType,
data:Vec<u8>,
}


pub struct MessageWithRollback{
msg_type:MessageType,
data:Vec<u8>,
rollback:Vec<u8>,
}


2 changes: 1 addition & 1 deletion contracts/cosmwasm-vm/cw-xcall/src/assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
8 changes: 4 additions & 4 deletions contracts/cosmwasm-vm/cw-xcall/src/execute_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
state::{CwCallService, EXECUTE_CALL_ID},
types::{
message::CSMessage,
response::{CSMessageResponse, CallServiceResponseType},
result::{CSMessageResult, CallServiceResponseType},
},
};

Expand Down Expand Up @@ -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,
);
Expand All @@ -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<SubMsg> = 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();
Expand Down
Loading

0 comments on commit f89db9d

Please sign in to comment.