Skip to content

Commit

Permalink
feat(ucs01-relay): call into diferredack module
Browse files Browse the repository at this point in the history
  • Loading branch information
PoisonPhang committed May 23, 2024
1 parent 7a07cf8 commit e5b6dea
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 93 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions cosmwasm/ucs01-relay-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ serde = { workspace = true }
sha2 = { workspace = true }
thiserror = { workspace = true }
token-factory-api = { workspace = true }
diferred-ack-api = { workspace = true }
unionlabs = { workspace = true }
protos = { workspace = true }
24 changes: 14 additions & 10 deletions cosmwasm/ucs01-relay-api/src/middleware.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use core::ops::Mul;
use std::ops::{Deref, DerefMut};

use cosmwasm_std::{Addr, Coin, Decimal};
use cosmwasm_std::{Addr, Binary, IbcTimeout};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use unionlabs::{
id::{ChannelId, PortId},
validated::{Validate, Validated},
};

use crate::types::EncodingError;

pub const DEFAULT_PFM_TIMEOUT: &str = "1m";
pub const DEFAULT_PFM_RETRIES: u8 = 0;
pub const PFM_MODULE_NAME: &str = "packetforwardmiddleware";
Expand All @@ -24,6 +26,8 @@ pub enum PacketForwardError {
NoPacketRefundInformation,
#[error("Unable to find a packet with the given refund index")]
PacketNotInRefundStore,
#[error("Unable to encode/decode packet")]
InvalidEncoding,
}

pub fn default_pfm_timeout() -> String {
Expand All @@ -34,17 +38,15 @@ pub fn default_pfm_retries() -> u8 {
DEFAULT_PFM_RETRIES
}

pub fn write_pfm_ack(in_flight_packet: InFlightPfmPacket) {}

#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub enum PacketReturnInfo {
InFlight(InFlightPfmPacket),
NewPacket(PacketSequence),
InFlight(Box<InFlightPfmPacket>),
NewPacket(PacketId),
}

/// Given that we can't know the IBC packet sequence of a new packet before it's sent, we instead construct and store this information about a packet to index it.
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct PacketSequence {
pub struct PacketId {
pub height: u64,
pub index: u32,
}
Expand All @@ -54,13 +56,15 @@ pub struct PacketSequence {
pub struct InFlightPfmPacket {
pub nonrefundable: bool,
pub original_sender_addr: Addr,
pub packet_data: String,
pub packet_data: Binary,
pub packet_src_channel_id: String,
pub packet_src_port_id: String,
pub refund_channel_id: String,
pub refund_port_id: String,
pub refund_sequence: PacketSequence,
pub refund_id: PacketId,
pub packet_sequence: u64,
pub timeout: u64,
pub src_packet_timeout: IbcTimeout,
}

#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
Expand All @@ -80,7 +84,7 @@ pub struct PacketForward {
#[serde(default = "default_pfm_retries")]
pub retries: u8,
pub next: Option<Box<PacketForward>>,
pub return_info: Option<PacketSequence>,
pub return_info: Option<PacketId>,
}

impl PacketForward {
Expand Down
98 changes: 57 additions & 41 deletions cosmwasm/ucs01-relay-api/src/protocol.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::fmt::Debug;

use cosmwasm_std::{
Addr, Attribute, Binary, Coin, CosmosMsg, Env, Event, IbcBasicResponse, IbcEndpoint, IbcMsg,
IbcOrder, IbcReceiveResponse, Response, SubMsg, Timestamp,
Addr, Attribute, Binary, Coin, CosmosMsg, Event, IbcBasicResponse, IbcEndpoint, IbcMsg,
IbcOrder, IbcPacket, IbcPacketAckMsg, IbcReceiveResponse, Response, SubMsg, Timestamp,
};
use thiserror::Error;

Expand Down Expand Up @@ -181,34 +181,42 @@ pub trait TransferProtocol {

fn send_ack(
&mut self,
raw_ack: impl Into<Binary> + Clone,
raw_packet: impl Into<Binary>,
ibc_packet: IbcPacketAckMsg,
) -> Result<IbcBasicResponse<Self::CustomMsg>, Self::Error> {
let packet = Self::Packet::try_from(raw_packet.into())?;
let packet = Self::Packet::try_from(ibc_packet.acknowledgement.data.clone())?;
// https://github.com/cosmos/ibc-go/blob/5ca37ef6e56a98683cf2b3b1570619dc9b322977/modules/apps/transfer/ibc_module.go#L261
let ack: GenericAck = Self::Ack::try_from(raw_ack.clone().into())?.into();
let ack: GenericAck = Self::Ack::try_from(ibc_packet.original_packet.data.clone())?.into();
let memo: String = packet.extension().clone().into();

if let Ok(Memo::Forward { forward }) = serde_json_wasm::from_str::<Memo>(&memo) {
return self.pfm_ack(ack, forward, packet.sender(), packet.tokens());
}

let (ack_msgs, ack_attr) = match ack {
Ok(value) => {
let value_string = value.to_string();
(
self.send_tokens_success(packet.sender(), packet.receiver(), packet.tokens())?,
(!value_string.is_empty()).then_some((ATTR_SUCCESS, value_string)),
)
}
Err(error) => {
let error_string = error.to_string();
(
self.send_tokens_failure(packet.sender(), packet.receiver(), packet.tokens())?,
(!error_string.is_empty()).then_some((ATTR_ERROR, error_string)),
)
}
};
let (ack_msgs, ack_attr) =
if let Ok(Memo::Forward { forward }) = serde_json_wasm::from_str::<Memo>(&memo) {
self.pfm_ack(ack, forward, packet.sender(), packet.tokens())?
} else {
match ack {
Ok(value) => {
let value_string = value.to_string();
(
self.send_tokens_success(
packet.sender(),
packet.receiver(),
packet.tokens(),
)?,
(!value_string.is_empty()).then_some((ATTR_SUCCESS, value_string)),
)
}
Err(error) => {
let error_string = error.to_string();
(
self.send_tokens_failure(
packet.sender(),
packet.receiver(),
packet.tokens(),
)?,
(!error_string.is_empty()).then_some((ATTR_ERROR, error_string)),
)
}
}
};

let packet_event = {
Event::new(PACKET_EVENT)
Expand All @@ -222,7 +230,7 @@ pub trait TransferProtocol {
(ATTR_MODULE, TRANSFER_MODULE),
(ATTR_SENDER, packet.sender().to_string().as_str()),
(ATTR_RECEIVER, packet.receiver().to_string().as_str()),
(ATTR_ACK, &raw_ack.into().to_string()),
(ATTR_ACK, &ibc_packet.acknowledgement.data.to_string()),
])
.add_attributes([tokens_to_attr(packet.tokens())]),
)
Expand All @@ -236,14 +244,17 @@ pub trait TransferProtocol {
) -> Result<IbcBasicResponse<Self::CustomMsg>, Self::Error> {
let packet = Self::Packet::try_from(raw_packet.into())?;
// same branch as failure ack
let refund_msgs =
self.send_tokens_failure(packet.sender(), packet.receiver(), packet.tokens())?;

let memo = Into::<String>::into(packet.extension().clone());
if let Ok(Memo::Forward { forward }) = serde_json_wasm::from_str::<Memo>(&memo) {
let ack = GenericAck::Err("giving up on forwarded packet after timeout".to_owned());
return self.pfm_ack(ack, forward, packet.sender(), packet.tokens());
}
let (refund_msgs, _) =
if let Ok(Memo::Forward { forward }) = serde_json_wasm::from_str::<Memo>(&memo) {
let ack = GenericAck::Err("giving up on forwarded packet after timeout".to_owned());
self.pfm_ack(ack, forward, packet.sender(), packet.tokens())?
} else {
(
self.send_tokens_failure(packet.sender(), packet.receiver(), packet.tokens())?,
None,
)
};

let timeout_event = if memo.is_empty() {
Event::new(PACKET_EVENT)
Expand All @@ -269,12 +280,9 @@ pub trait TransferProtocol {
tokens: Vec<TransferToken>,
) -> Result<Vec<CosmosMsg<Self::CustomMsg>>, Self::Error>;

fn receive(
&mut self,
raw_packet: impl Into<Binary> + Clone,
) -> IbcReceiveResponse<Self::CustomMsg> {
fn receive(&mut self, original_packet: IbcPacket) -> IbcReceiveResponse<Self::CustomMsg> {
let mut handle = || -> Result<IbcReceiveResponse<Self::CustomMsg>, Self::Error> {
let packet = Self::Packet::try_from(raw_packet.clone().into())?;
let packet = Self::Packet::try_from(original_packet.data.clone())?;

// NOTE: The default message ack is always successful and only
// overwritten if the submessage execution revert via the reply
Expand All @@ -291,7 +299,13 @@ pub trait TransferProtocol {
if let Ok(memo) = serde_json_wasm::from_str::<Memo>(&memo) {
match memo {
Memo::Forward { forward } => {
return Ok(Self::packet_forward(self, packet, forward, false))
return Ok(Self::packet_forward(
self,
packet,
original_packet,
forward,
false,
))
}
Memo::None {} => {}
};
Expand Down Expand Up @@ -341,13 +355,15 @@ pub trait TransferProtocol {
fn packet_forward(
&mut self,
packet: Self::Packet,
original_packet: IbcPacket,
forward: PacketForward,
processed: bool,
) -> IbcReceiveResponse<Self::CustomMsg>;

fn forward_transfer_packet(
&mut self,
tokens: Vec<Coin>,
original_packet: IbcPacket,
forward: PacketForward,
receiver: Addr,
nonrefundable: bool,
Expand All @@ -360,7 +376,7 @@ pub trait TransferProtocol {
original_forward_packet: PacketForward,
sender: &<Self::Packet as TransferPacket>::Addr,
tokens: Vec<TransferToken>,
) -> Result<IbcBasicResponse<Self::CustomMsg>, Self::Error>;
) -> Result<(Vec<CosmosMsg<Self::CustomMsg>>, Option<(&str, String)>), Self::Error>;
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions cosmwasm/ucs01-relay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ serde = { workspace = true, features = ["derive"] }
sha2 = { workspace = true }
thiserror = { workspace = true }
token-factory-api = { workspace = true }
diferred-ack-api = { workspace = true }
ucs01-relay-api = { workspace = true }
protos = { workspace = true }
10 changes: 5 additions & 5 deletions cosmwasm/ucs01-relay/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ pub fn ibc_packet_receive(
channel: channel_info,
},
}
.receive(msg.packet.data)),
.receive(msg.packet)),
Ucs01Protocol::VERSION => Ok(Ucs01Protocol {
common: ProtocolCommon {
deps,
Expand All @@ -158,7 +158,7 @@ pub fn ibc_packet_receive(
channel: channel_info,
},
}
.receive(msg.packet.data)),
.receive(msg.packet)),
v => Err(ContractError::UnknownProtocol {
channel_id: msg.packet.dest.channel_id,
protocol_version: v.into(),
Expand All @@ -176,7 +176,7 @@ pub fn ibc_packet_ack(
let channel_info = CHANNEL_INFO.load(deps.storage, &msg.original_packet.src.channel_id)?;

let info = MessageInfo {
sender: msg.relayer,
sender: msg.clone().relayer,
funds: Default::default(),
};

Expand All @@ -189,7 +189,7 @@ pub fn ibc_packet_ack(
channel: channel_info,
},
}
.send_ack(msg.acknowledgement.data, msg.original_packet.data),
.send_ack(msg),
Ucs01Protocol::VERSION => Ucs01Protocol {
common: ProtocolCommon {
deps,
Expand All @@ -198,7 +198,7 @@ pub fn ibc_packet_ack(
channel: channel_info,
},
}
.send_ack(msg.acknowledgement.data, msg.original_packet.data),
.send_ack(msg),
v => Err(ContractError::UnknownProtocol {
channel_id: msg.original_packet.dest.channel_id,
protocol_version: v.into(),
Expand Down
Loading

0 comments on commit e5b6dea

Please sign in to comment.