Skip to content

Commit

Permalink
fix coding for ack and ftt
Browse files Browse the repository at this point in the history
  • Loading branch information
yito88 committed Jul 11, 2022
1 parent 6865704 commit dae0758
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 67 deletions.
81 changes: 52 additions & 29 deletions shared/src/ledger/ibc/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,10 +605,17 @@ pub trait IbcActions {

/// Receive a packet
fn receive_packet(&self, msg: &MsgRecvPacket) -> Result<()> {
// TODO for other applications
// 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(e) => PacketAck::result_error(e.to_string()),
}
} else {
PacketAck::result_error("unknown packet data".to_string())
};

// store the receipt
let receipt_key = storage::receipt_key(
Expand All @@ -624,7 +631,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 @@ -646,13 +653,30 @@ pub trait IbcActions {

/// Receive a acknowledgement
fn acknowledge_packet(&self, msg: &MsgAcknowledgement) -> Result<()> {
let ack = PacketAck::try_from(msg.acknowledgement.clone())
.map_err(Error::IbcData)?;
if !ack.is_success() {
// TODO for other applications
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 All @@ -661,6 +685,7 @@ pub trait IbcActions {

/// Receive a timeout
fn timeout_packet(&self, msg: &MsgTimeout) -> Result<()> {
// TODO for other applications
// check the packet data
if let Ok(data) = serde_json::from_slice(&msg.packet.data) {
self.refund_token(&msg.packet, &data)?;
Expand Down Expand Up @@ -704,6 +729,7 @@ pub trait IbcActions {

/// Receive a timeout for TimeoutOnClose
fn timeout_on_close_packet(&self, msg: &MsgTimeoutOnClose) -> Result<()> {
// TODO for other applications
// check the packet data
if let Ok(data) = serde_json::from_slice(&msg.packet.data) {
self.refund_token(&msg.packet, &data)?;
Expand Down Expand Up @@ -824,13 +850,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 @@ -844,13 +869,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 @@ -889,13 +914,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 @@ -914,7 +938,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 @@ -942,13 +966,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 @@ -967,7 +990,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 @@ -1446,7 +1446,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 @@ -1516,7 +1516,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 @@ -1689,7 +1689,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 @@ -1730,7 +1730,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
19 changes: 8 additions & 11 deletions shared/src/ledger/ibc/vp/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,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 @@ -171,8 +170,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 @@ -181,7 +179,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 @@ -220,18 +218,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
Loading

0 comments on commit dae0758

Please sign in to comment.