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 11 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
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,49 @@ impl From<MsgTransfer> for RawMsgTransfer {
}
}
}

#[cfg(test)]
pub mod test_util {

use super::MsgTransfer;
use crate::{
ics24_host::identifier::{ChannelId, PortId},
test_utils::get_dummy_account_id,
Height,
};
use ibc_proto::ibc::applications::transfer::v1::MsgTransfer as RawMsgTransfer;
use ibc_proto::ibc::core::client::v1::Height as RawHeight;

// 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,
receiver: id,
timeout_timestamp: 1,
timeout_height: Height {
revision_number: 0,
revision_height: height,
},
}
}
// Returns a dummy `RawMsgTransfer`, for testing only!
pub fn get_dummy_raw_msg_transfer(height: u64) -> RawMsgTransfer {
RawMsgTransfer {
source_port: PortId::default().to_string(),
source_channel: ChannelId::default().to_string(),
token: Default::default(),
sender: Default::default(),
receiver: Default::default(),
timeout_height: Some(RawHeight {
revision_number: 0,
revision_height: height,
}),
timeout_timestamp: 1,
}
}
}
123 changes: 122 additions & 1 deletion modules/src/ics02_client/client_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use prost_types::Any;
use serde::Serialize;
use tendermint_proto::Protobuf;

use crate::downcast;
use crate::ics02_client::client_type::ClientType;
use crate::ics02_client::error::{Error, Kind};
use crate::ics02_client::header::Header;
Expand All @@ -19,6 +18,7 @@ use crate::ics07_tendermint::header::Header as TendermintHeader;
use crate::ics23_commitment::commitment::{CommitmentPrefix, CommitmentProofBytes, CommitmentRoot};
use crate::ics24_host::identifier::{ChainId, ChannelId, ClientId, ConnectionId, PortId};
use crate::Height;
use crate::{downcast, ics04_channel::packet::Sequence};

#[cfg(any(test, feature = "mocks"))]
use crate::mock::{
Expand Down Expand Up @@ -103,6 +103,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)] // TODO: Add Eq bound once possible
Expand Down Expand Up @@ -618,6 +644,101 @@ 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,
)
}
}
}
}

#[cfg(test)]
Expand Down
76 changes: 75 additions & 1 deletion modules/src/ics04_channel/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use crate::ics02_client::client_def::{AnyClientState, AnyConsensusState};
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 @@ -37,9 +37,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 @@ -97,6 +113,47 @@ pub trait ChannelKeeper {
res.data,
)?;
}
PacketResult::Recv(res) => {
match res.receipt {
None => {
//Ordered cchannel
adizere marked this conversation as resolved.
Show resolved Hide resolved
self.store_next_sequence_recv(
(res.port_id.clone(), res.channel_id.clone()),
res.seq_number,
)?
}
Some(r) => {
//Unorderd channel
adizere marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -109,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 receving 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
17 changes: 16 additions & 1 deletion modules/src/ics04_channel/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ use crate::ics04_channel::msgs::ChannelMsg;
use crate::ics05_port::capabilities::Capability;
use crate::ics24_host::identifier::{ChannelId, PortId};

use super::{msgs::PacketMsg, packet::PacketResult};

pub mod acknowledgement;
pub mod chan_close_confirm;
pub mod chan_close_init;
pub mod chan_open_ack;
pub mod chan_open_confirm;
pub mod chan_open_init;
pub mod chan_open_try;
pub mod recv_packet;
pub mod send_packet;

mod verify;
pub mod write_acknowledgement;

/// Defines the possible states of a channel identifier in a `ChannelResult`.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -53,3 +57,14 @@ where
ChannelMsg::ChannelCloseConfirm(msg) => chan_close_confirm::process(ctx, msg),
}
}

pub fn packet_dispatch<Ctx>(ctx: &Ctx, msg: PacketMsg) -> Result<HandlerOutput<PacketResult>, Error>
where
Ctx: ChannelReader,
{
match msg {
PacketMsg::RecvPacket(msg) => recv_packet::process(ctx, msg),
PacketMsg::AckPacket(msg) => acknowledgement::process(ctx, msg),
_ => todo!(),
}
}
Loading