Skip to content

Commit

Permalink
Merge branch 'yuji/ibc_ack_ftt_coding' (#261)
Browse files Browse the repository at this point in the history
* yuji/ibc_ack_ftt_coding:
  [ci] wasm checksums update
  fix IBC token VP for ack error
  fix coding for ack and ftt
  • Loading branch information
tzemanovic committed Oct 20, 2022
2 parents 836a6de + 3b8f1dd commit 9ba054d
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 83 deletions.
79 changes: 50 additions & 29 deletions shared/src/ledger/ibc/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,17 @@ pub trait IbcActions {
msg: &MsgRecvPacket,
) -> std::result::Result<(), Self::Error> {
// check the packet data
if let Ok(data) = serde_json::from_slice(&msg.packet.data) {
self.receive_token(&msg.packet, &data)?;
}
let packet_ack =
if let Ok(data) = serde_json::from_slice(&msg.packet.data) {
match self.receive_token(&msg.packet, &data) {
Ok(_) => PacketAck::result_success(),
Err(_) => PacketAck::result_error(
"receiving a token failed".to_string(),
),
}
} else {
PacketAck::result_error("unknown packet data".to_string())
};

// store the receipt
let receipt_key = storage::receipt_key(
Expand All @@ -693,7 +701,7 @@ pub trait IbcActions {
&msg.packet.destination_channel,
msg.packet.sequence,
);
let ack = PacketAck::default().encode_to_vec();
let ack = packet_ack.encode_to_vec();
let ack_commitment = sha2::Sha256::digest(&ack).to_vec();
self.write_ibc_data(&ack_key, ack_commitment)?;

Expand All @@ -718,13 +726,29 @@ pub trait IbcActions {
&mut self,
msg: &MsgAcknowledgement,
) -> std::result::Result<(), Self::Error> {
let ack = PacketAck::try_from(msg.acknowledgement.clone())
.map_err(Error::IbcData)?;
if !ack.is_success() {
if let Ok(data) = serde_json::from_slice(&msg.packet.data) {
self.refund_token(&msg.packet, &data)?;
}
}

let commitment_key = storage::commitment_key(
&msg.packet.source_port,
&msg.packet.source_channel,
msg.packet.sequence,
);
self.delete_ibc_data(&commitment_key)?;

// get and increment the next sequence ack
let port_channel_id = port_channel_id(
msg.packet.source_port.clone(),
msg.packet.source_channel,
);
let seq_key = storage::next_sequence_ack_key(&port_channel_id);
self.get_and_inc_sequence(&seq_key)?;

let event = make_ack_event(msg.packet.clone()).try_into().unwrap();
self.emit_ibc_event(event)?;

Expand Down Expand Up @@ -917,13 +941,12 @@ pub trait IbcActions {
data.sender, e
))
})?;
let token_str =
data.denomination.split('/').last().ok_or_else(|| {
Error::SendingToken(format!(
"No token was specified: {}",
data.denomination
))
})?;
let token_str = data.denom.split('/').last().ok_or_else(|| {
Error::SendingToken(format!(
"No token was specified: {}",
data.denom
))
})?;
let token = Address::decode(token_str).map_err(|e| {
Error::SendingToken(format!(
"Invalid token address: token {}, error {}",
Expand All @@ -937,13 +960,13 @@ pub trait IbcActions {
))
})?;

// check the denomination field
// check the denom field
let prefix = format!(
"{}/{}/",
msg.source_port.clone(),
msg.source_channel.clone()
);
if data.denomination.starts_with(&prefix) {
if data.denom.starts_with(&prefix) {
// sink zone
let burn = Address::Internal(InternalAddress::IbcBurn);
self.transfer_token(&source, &burn, &token, amount)?;
Expand Down Expand Up @@ -982,13 +1005,12 @@ pub trait IbcActions {
data.receiver, e
))
})?;
let token_str =
data.denomination.split('/').last().ok_or_else(|| {
Error::ReceivingToken(format!(
"No token was specified: {}",
data.denomination
))
})?;
let token_str = data.denom.split('/').last().ok_or_else(|| {
Error::ReceivingToken(format!(
"No token was specified: {}",
data.denom
))
})?;
let token = Address::decode(token_str).map_err(|e| {
Error::ReceivingToken(format!(
"Invalid token address: token {}, error {}",
Expand All @@ -1007,7 +1029,7 @@ pub trait IbcActions {
packet.source_port.clone(),
packet.source_channel.clone()
);
if data.denomination.starts_with(&prefix) {
if data.denom.starts_with(&prefix) {
// unescrow the token because this chain is the source
let escrow =
Address::Internal(InternalAddress::ibc_escrow_address(
Expand Down Expand Up @@ -1035,13 +1057,12 @@ pub trait IbcActions {
data.sender, e
))
})?;
let token_str =
data.denomination.split('/').last().ok_or_else(|| {
Error::ReceivingToken(format!(
"No token was specified: {}",
data.denomination
))
})?;
let token_str = data.denom.split('/').last().ok_or_else(|| {
Error::ReceivingToken(format!(
"No token was specified: {}",
data.denom
))
})?;
let token = Address::decode(token_str).map_err(|e| {
Error::ReceivingToken(format!(
"Invalid token address: token {}, error {}",
Expand All @@ -1060,7 +1081,7 @@ pub trait IbcActions {
packet.source_port.clone(),
packet.source_channel.clone()
);
if data.denomination.starts_with(&prefix) {
if data.denom.starts_with(&prefix) {
// mint the token because the sender chain is the sink zone
let mint = Address::Internal(InternalAddress::IbcMint);
self.transfer_token(&mint, &dest, &token, amount)?;
Expand Down
8 changes: 4 additions & 4 deletions shared/src/ledger/ibc/vp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1570,7 +1570,7 @@ mod tests {
.write(&key, PacketReceipt::default().as_bytes().to_vec())
.expect("write failed");
let key = ack_key(&get_port_id(), &get_channel_id(), sequence);
let ack = PacketAck::default().encode_to_vec();
let ack = PacketAck::result_success().encode_to_vec();
write_log.write(&key, ack).expect("write failed");

let tx_code = vec![];
Expand Down Expand Up @@ -1648,7 +1648,7 @@ mod tests {
write_log.commit_block(&mut storage).expect("commit failed");

// prepare data
let ack = PacketAck::default().encode_to_vec();
let ack = PacketAck::result_success().encode_to_vec();
let proof_packet = CommitmentProofBytes::try_from(vec![0]).unwrap();
let proofs =
Proofs::new(proof_packet, None, None, None, Height::new(0, 1))
Expand Down Expand Up @@ -1837,7 +1837,7 @@ mod tests {
&msg.packet.destination_channel,
msg.packet.sequence,
);
let ack = PacketAck::default().encode_to_vec();
let ack = PacketAck::result_success().encode_to_vec();
write_log.write(&ack_key, ack).expect("write failed");
write_log.commit_tx();

Expand Down Expand Up @@ -1886,7 +1886,7 @@ mod tests {
.expect("write failed");
let ack_key =
ack_key(&get_port_id(), &get_channel_id(), Sequence::from(1));
let ack = PacketAck::default().encode_to_vec();
let ack = PacketAck::result_success().encode_to_vec();
write_log.write(&ack_key, ack).expect("write failed");
write_log.commit_tx();

Expand Down
22 changes: 11 additions & 11 deletions shared/src/ledger/ibc/vp/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ where
Ics26Envelope::Ics4PacketMsg(PacketMsg::RecvPacket(msg)) => {
self.validate_receiving_token(&msg.packet)
}
Ics26Envelope::Ics4PacketMsg(PacketMsg::AckPacket(msg)) => {
self.validate_refunding_token(&msg.packet)
}
Ics26Envelope::Ics4PacketMsg(PacketMsg::ToPacket(msg)) => {
self.validate_refunding_token(&msg.packet)
}
Expand All @@ -121,18 +124,17 @@ where
{
fn validate_sending_token(&self, msg: &MsgTransfer) -> Result<bool> {
let data = FungibleTokenPacketData::from(msg.clone());
let token_str =
data.denomination.split('/').last().ok_or(Error::NoToken)?;
let token_str = data.denom.split('/').last().ok_or(Error::NoToken)?;
let token = Address::decode(token_str).map_err(Error::Address)?;
let amount = Amount::from_str(&data.amount).map_err(Error::Amount)?;

// check the denomination field
// check the denom field
let prefix = format!(
"{}/{}/",
msg.source_port.clone(),
msg.source_channel.clone()
);
let change = if data.denomination.starts_with(&prefix) {
let change = if data.denom.starts_with(&prefix) {
// sink zone
let target = Address::Internal(InternalAddress::IbcBurn);
let target_key = token::balance_key(&token, &target);
Expand Down Expand Up @@ -174,8 +176,7 @@ where
let data: FungibleTokenPacketData =
serde_json::from_slice(&packet.data)
.map_err(Error::DecodingPacketData)?;
let token_str =
data.denomination.split('/').last().ok_or(Error::NoToken)?;
let token_str = data.denom.split('/').last().ok_or(Error::NoToken)?;
let token = Address::decode(token_str).map_err(Error::Address)?;
let amount = Amount::from_str(&data.amount).map_err(Error::Amount)?;

Expand All @@ -184,7 +185,7 @@ where
packet.source_port.clone(),
packet.source_channel.clone()
);
let change = if data.denomination.starts_with(&prefix) {
let change = if data.denom.starts_with(&prefix) {
// this chain is the source
let source =
Address::Internal(InternalAddress::ibc_escrow_address(
Expand Down Expand Up @@ -226,18 +227,17 @@ where
let data: FungibleTokenPacketData =
serde_json::from_slice(&packet.data)
.map_err(Error::DecodingPacketData)?;
let token_str =
data.denomination.split('/').last().ok_or(Error::NoToken)?;
let token_str = data.denom.split('/').last().ok_or(Error::NoToken)?;
let token = Address::decode(token_str).map_err(Error::Address)?;
let amount = Amount::from_str(&data.amount).map_err(Error::Amount)?;

// check the denomination field
// check the denom field
let prefix = format!(
"{}/{}/",
packet.source_port.clone(),
packet.source_channel.clone()
);
let change = if data.denomination.starts_with(&prefix) {
let change = if data.denom.starts_with(&prefix) {
// sink zone: mint the token for the refund
let source = Address::Internal(InternalAddress::IbcMint);
let source_key = token::balance_key(&token, &source);
Expand Down
63 changes: 48 additions & 15 deletions shared/src/types/ibc/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use crate::ibc::core::ics03_connection::msgs::conn_open_confirm::MsgConnectionOp
use crate::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit;
use crate::ibc::core::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry;
use crate::ibc::core::ics03_connection::msgs::ConnectionMsg;
use crate::ibc::core::ics04_channel::msgs::acknowledgement::MsgAcknowledgement;
use crate::ibc::core::ics04_channel::msgs::acknowledgement::{
Acknowledgement, MsgAcknowledgement,
};
use crate::ibc::core::ics04_channel::msgs::chan_close_confirm::MsgChannelCloseConfirm;
use crate::ibc::core::ics04_channel::msgs::chan_close_init::MsgChannelCloseInit;
use crate::ibc::core::ics04_channel::msgs::chan_open_ack::MsgChannelOpenAck;
Expand All @@ -32,14 +34,14 @@ use crate::ibc::core::ics26_routing::error::Error as Ics26Error;
use crate::ibc::core::ics26_routing::msgs::Ics26Envelope;
use crate::ibc::downcast;
use crate::ibc_proto::google::protobuf::Any;
use crate::ibc_proto::ibc::core::channel::v1::acknowledgement::Response;
use crate::ibc_proto::ibc::core::channel::v1::Acknowledgement;

#[allow(missing_docs)]
#[derive(Error, Debug)]
pub enum Error {
#[error("Decoding IBC data error: {0}")]
DecodingData(prost::DecodeError),
#[error("Decoding Json data error: {0}")]
DecodingJsonData(serde_json::Error),
#[error("Decoding message error: {0}")]
DecodingMessage(Ics26Error),
#[error("Downcast error: {0}")]
Expand Down Expand Up @@ -326,39 +328,70 @@ impl Default for PacketReceipt {
}

/// Acknowledgement for a packet
#[derive(Clone, Debug)]
pub struct PacketAck(pub Acknowledgement);
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PacketAck {
/// Success Acknowledgement
Result(String),
/// Error Acknowledgement
Error(String),
}

/// Success acknowledgement
const ACK_SUCCESS_B64: &str = "AQ==";
/// Error acknowledgement
const ACK_ERR_STR: &str =
"error handling packet on destination chain: see events for details";

// TODO temporary type. add a new type for ack to ibc-rs
impl PacketAck {
/// Success acknowledgement
pub fn result_success() -> Self {
Self::Result(ACK_SUCCESS_B64.to_string())
}

/// Acknowledgement with an error
pub fn result_error(err: String) -> Self {
Self::Error(format!("{}: {}", ACK_ERR_STR, err))
}

/// Check if the ack is for success
pub fn is_success(&self) -> bool {
match self {
Self::Result(_) => true,
Self::Error(_) => false,
}
}

/// Encode the ack
pub fn encode_to_vec(&self) -> Vec<u8> {
serde_json::to_vec(&self.0)
serde_json::to_vec(&self)
.expect("Encoding acknowledgement shouldn't fail")
}
}

impl Default for PacketAck {
fn default() -> Self {
Self(Acknowledgement {
response: Some(Response::Result(vec![1_u8])),
})
impl TryFrom<Acknowledgement> for PacketAck {
type Error = Error;

fn try_from(ack: Acknowledgement) -> Result<Self> {
serde_json::from_slice(&ack.into_bytes())
.map_err(Error::DecodingJsonData)
}
}

// for the string to be used by the current reader
impl Display for PacketAck {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", serde_json::to_string(&self.0).unwrap())
write!(f, "{}", serde_json::to_string(&self).unwrap())
}
}

// TODO temporary type. add a new type for ack to ibc-rs
// TODO temporary type. add a new type for packet data to ibc-rs
/// Data to transfer a token
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct FungibleTokenPacketData {
/// the token denomination to be transferred
pub denomination: String,
pub denom: String,
/// the token amount to be transferred
pub amount: String,
/// the sender address
Expand All @@ -372,7 +405,7 @@ impl From<MsgTransfer> for FungibleTokenPacketData {
// TODO validation
let token = msg.token.unwrap();
Self {
denomination: token.denom,
denom: token.denom,
amount: token.amount,
sender: msg.sender.to_string(),
receiver: msg.receiver.to_string(),
Expand Down
7 changes: 2 additions & 5 deletions shared/src/types/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,8 @@ impl TryFrom<FungibleTokenPacketData> for Transfer {
Address::decode(&data.sender).map_err(TransferError::Address)?;
let target =
Address::decode(&data.receiver).map_err(TransferError::Address)?;
let token_str = data
.denomination
.split('/')
.last()
.ok_or(TransferError::NoToken)?;
let token_str =
data.denom.split('/').last().ok_or(TransferError::NoToken)?;
let token =
Address::decode(token_str).map_err(TransferError::Address)?;
let amount =
Expand Down
Loading

0 comments on commit 9ba054d

Please sign in to comment.