Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ics04 packet recv write_ack ack #737

Merged
merged 21 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
### FEATURES

- [ibc]
- Added handler(s) for sending packets ([#695])
- Added handler(s) for sending packets ([#695]) and for recv. and ack. packets ([#736])

- [ibc-relayer]
- Support for relayer restart ([#561])
Expand Down Expand Up @@ -68,6 +68,7 @@
[#699]: https://github.com/informalsystems/ibc-rs/issues/699
[#700]: https://github.com/informalsystems/ibc-rs/pull/700
[#702]: https://github.com/informalsystems/ibc-rs/issues/702
[#736]: https://github.com/informalsystems/ibc-rs/issues/736
[#740]: https://github.com/informalsystems/ibc-rs/issues/740

## v0.1.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

use std::convert::{TryFrom, TryInto};

use ibc_proto::ibc::apps::transfer::v1::MsgTransfer as RawMsgTransfer;
use tendermint_proto::Protobuf;

use ibc_proto::ibc::apps::transfer::v1::MsgTransfer as RawMsgTransfer;

use crate::application::ics20_fungible_token_transfer::error::{Error, Kind};
use crate::ics02_client::height::Height;
use crate::ics24_host::identifier::{ChannelId, PortId};
Expand Down Expand Up @@ -62,7 +63,7 @@ impl TryFrom<RawMsgTransfer> for MsgTransfer {
sender: raw_msg.sender.into(),
receiver: raw_msg.receiver.into(),
timeout_height: raw_msg.timeout_height.unwrap().try_into().unwrap(),
timeout_timestamp: 0,
timeout_timestamp: raw_msg.timeout_timestamp,
})
}
}
Expand All @@ -76,7 +77,36 @@ impl From<MsgTransfer> for RawMsgTransfer {
sender: domain_msg.sender.to_string(),
receiver: domain_msg.receiver.to_string(),
timeout_height: Some(domain_msg.timeout_height.try_into().unwrap()),
timeout_timestamp: 0,
timeout_timestamp: domain_msg.timeout_timestamp,
}
}
}

#[cfg(test)]
pub mod test_util {
use crate::{
ics24_host::identifier::{ChannelId, PortId},
test_utils::get_dummy_account_id,
Height,
};

use super::MsgTransfer;

// Returns a dummy `RawMsgTransfer`, for testing only!
pub fn get_dummy_msg_transfer(height: u64) -> MsgTransfer {
let id = get_dummy_account_id();

MsgTransfer {
source_port: PortId::default(),
source_channel: ChannelId::default(),
token: None,
sender: id.clone(),
receiver: id,
timeout_timestamp: 1,
timeout_height: Height {
revision_number: 0,
revision_height: height,
},
}
}
}
125 changes: 124 additions & 1 deletion modules/src/ics02_client/client_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ use crate::ics02_client::error::Kind;
use crate::ics02_client::header::{AnyHeader, Header};
use crate::ics03_connection::connection::ConnectionEnd;
use crate::ics04_channel::channel::ChannelEnd;
use crate::ics04_channel::packet::Sequence;
use crate::ics07_tendermint::client_def::TendermintClient;
use crate::ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes, CommitmentRoot};
use crate::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId};
use crate::Height;

#[cfg(any(test, feature = "mocks"))]
use crate::mock::client_def::MockClient;
use crate::Height;

pub trait ClientDef: Clone {
type Header: Header;
Expand Down Expand Up @@ -80,6 +82,32 @@ pub trait ClientDef: Clone {
proof: &CommitmentProofBytes,
client_state: &AnyClientState,
) -> Result<(), Box<dyn std::error::Error>>;

/// Verify a `proof` that a packet has been commited.
#[allow(clippy::too_many_arguments)]
fn verify_packet_data(
&self,
client_state: &Self::ClientState,
height: Height,
proof: &CommitmentProofBytes,
port_id: &PortId,
channel_id: &ChannelId,
seq: &Sequence,
commitment: String,
) -> Result<(), Box<dyn std::error::Error>>;

/// Verify a `proof` that a packet has been commited.
#[allow(clippy::too_many_arguments)]
fn verify_packet_acknowledgement(
&self,
client_state: &Self::ClientState,
height: Height,
proof: &CommitmentProofBytes,
port_id: &PortId,
channel_id: &ChannelId,
seq: &Sequence,
ack: Vec<u8>,
) -> Result<(), Box<dyn std::error::Error>>;
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -329,4 +357,99 @@ impl ClientDef for AnyClient {
}
}
}
fn verify_packet_data(
&self,
client_state: &Self::ClientState,
height: Height,
proof: &CommitmentProofBytes,
port_id: &PortId,
channel_id: &ChannelId,
seq: &Sequence,
commitment: String,
) -> Result<(), Box<dyn std::error::Error>> {
match self {
Self::Tendermint(client) => {
let client_state = downcast!(
client_state => AnyClientState::Tendermint
)
.ok_or_else(|| Kind::ClientArgsTypeMismatch(ClientType::Tendermint))?;

client.verify_packet_data(
client_state,
height,
proof,
port_id,
channel_id,
seq,
commitment,
)
}

#[cfg(any(test, feature = "mocks"))]
Self::Mock(client) => {
let client_state = downcast!(
client_state => AnyClientState::Mock
)
.ok_or_else(|| Kind::ClientArgsTypeMismatch(ClientType::Mock))?;

client.verify_packet_data(
client_state,
height,
proof,
port_id,
channel_id,
seq,
commitment,
)
}
}
}

fn verify_packet_acknowledgement(
&self,
client_state: &Self::ClientState,
height: Height,
proof: &CommitmentProofBytes,
port_id: &PortId,
channel_id: &ChannelId,
seq: &Sequence,
ack: Vec<u8>,
) -> Result<(), Box<dyn std::error::Error>> {
match self {
Self::Tendermint(client) => {
let client_state = downcast!(
client_state => AnyClientState::Tendermint
)
.ok_or_else(|| Kind::ClientArgsTypeMismatch(ClientType::Tendermint))?;

client.verify_packet_acknowledgement(
client_state,
height,
proof,
port_id,
channel_id,
seq,
ack,
)
}

#[cfg(any(test, feature = "mocks"))]
Self::Mock(client) => {
let client_state = downcast!(
client_state => AnyClientState::Mock
)
.ok_or_else(|| Kind::ClientArgsTypeMismatch(ClientType::Mock))?;

client.verify_packet_acknowledgement(
client_state,
height,
proof,
port_id,
channel_id,
seq,
ack,
)
}
}
}
}
75 changes: 74 additions & 1 deletion modules/src/ics04_channel/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::ics02_client::client_consensus::AnyConsensusState;
use crate::ics02_client::client_state::AnyClientState;
use crate::ics03_connection::connection::ConnectionEnd;
use crate::ics04_channel::channel::ChannelEnd;
use crate::ics04_channel::error::Error;
use crate::ics04_channel::handler::{ChannelIdState, ChannelResult};
use crate::ics04_channel::{error::Error, packet::Receipt};
use crate::ics05_port::capabilities::Capability;
use crate::ics24_host::identifier::{ChannelId, ClientId, ConnectionId, PortId};
use crate::Height;
Expand Down Expand Up @@ -38,9 +38,25 @@ pub trait ChannelReader {

fn get_next_sequence_send(&self, port_channel_id: &(PortId, ChannelId)) -> Option<Sequence>;

fn get_next_sequence_recv(&self, port_channel_id: &(PortId, ChannelId)) -> Option<Sequence>;
adizere marked this conversation as resolved.
Show resolved Hide resolved

fn get_next_sequence_ack(&self, port_channel_id: &(PortId, ChannelId)) -> Option<Sequence>;

fn get_packet_commitment(&self, key: &(PortId, ChannelId, Sequence)) -> Option<String>;

fn get_packet_receipt(&self, key: &(PortId, ChannelId, Sequence)) -> Option<Receipt>;

fn get_packet_acknowledgement(&self, key: &(PortId, ChannelId, Sequence)) -> Option<String>;

/// A hashing function for packet commitments
fn hash(&self, value: String) -> String;

/// Returns the current height of the local chain.
fn host_height(&self) -> Height;

/// Returns the current timestamp of the local chain.
fn host_timestamp(&self) -> u64;
Copy link
Member

@romac romac Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could introduce a newtype wrapper for the timestamp, here and in other places where we currently use a u64, eg. a pub struct Timestamp { seconds: u64 } in the host module.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


/// Returns a counter on the number of channel ids have been created thus far.
/// The value of this counter should increase only via method
/// `ChannelKeeper::increase_channel_counter`.
Expand Down Expand Up @@ -98,6 +114,46 @@ pub trait ChannelKeeper {
res.data,
)?;
}
PacketResult::Recv(res) => {
match res.receipt {
None => {
// Ordered channel
self.store_next_sequence_recv(
(res.port_id.clone(), res.channel_id.clone()),
res.seq_number,
)?
}
Some(r) => {
// Unordered channel
self.store_packet_receipt(
(res.port_id.clone(), res.channel_id.clone(), res.seq),
r,
)?
}
}
}
PacketResult::WriteAck(res) => {
self.store_packet_acknowledgement(
(res.port_id.clone(), res.channel_id.clone(), res.seq),
res.ack,
)?;
}
PacketResult::Ack(res) => {
match res.seq_number {
Some(s) => {
//Ordered Channel
self.store_next_sequence_ack((res.port_id.clone(), res.channel_id), s)?;
}
None => {
//Unorderded Channel
self.delete_packet_acknowledgement((
res.port_id.clone(),
res.channel_id.clone(),
res.seq,
))?;
}
}
}
}
Ok(())
}
Expand All @@ -110,6 +166,23 @@ pub trait ChannelKeeper {
data: Vec<u8>,
) -> Result<(), Error>;

fn store_packet_receipt(
&mut self,
key: (PortId, ChannelId, Sequence),
receipt: Receipt,
) -> Result<(), Error>;

fn store_packet_acknowledgement(
&mut self,
key: (PortId, ChannelId, Sequence),
ack: Vec<u8>,
) -> Result<(), Error>;

fn delete_packet_acknowledgement(
&mut self,
key: (PortId, ChannelId, Sequence),
) -> Result<(), Error>;

fn store_connection_channels(
&mut self,
conn_id: ConnectionId,
Expand Down
24 changes: 24 additions & 0 deletions modules/src/ics04_channel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub enum Kind {
#[error("invalid proof: missing height")]
MissingHeight,

#[error("Missing sequence number for receiving packets")]
MissingNextRecvSeq,

#[error("packet sequence cannot be 0")]
ZeroPacketSequence,

Expand All @@ -55,6 +58,9 @@ pub enum Kind {
#[error("there is no packet in this message")]
MissingPacket,

#[error("Packet with the sequence number {0} has been already received")]
PacketAlreadyReceived(Sequence),

#[error("missing counterparty")]
MissingCounterparty,
#[error("no commong version")]
Expand Down Expand Up @@ -95,6 +101,15 @@ pub enum Kind {
#[error("Channel chain verification fails on ChannelOpenTry for ChannelOpenInit")]
FailedChanneOpenTryVerification,

#[error("Verification fails for the packet with the sequence number {0}")]
PacketVerificationFailed(Sequence),

#[error("Acknowledgment cannot be empty")]
InvalidAcknowledgement,

#[error("Packet acknowledgement exists for the packet with the sequence {0}")]
AcknowledgementExists(Sequence),

#[error("No client state associated with client id {0}")]
MissingClientState(ClientId),

Expand Down Expand Up @@ -134,8 +149,17 @@ pub enum Kind {
#[error("Handshake proof verification fails at ChannelOpenAck")]
ChanOpenAckProofVerification,

#[error("Commitment for the packet {0} not found")]
PacketCommitmentNotFound(Sequence),

#[error("Handshake proof verification fails at ChannelOpenConfirm")]
ChanOpenConfirmProofVerification,

#[error("The stored commitment of the packet {0} is incorrect")]
IncorrectPacketCommitment(Sequence),

#[error("Missing sequence number for ack packets")]
MissingNextAckSeq,
}

impl Kind {
Expand Down
Loading