Skip to content

Commit

Permalink
Merge branch 'master' into vitor/ics02_mbt
Browse files Browse the repository at this point in the history
  • Loading branch information
vitorenesduarte committed Feb 11, 2021
2 parents 60e4aba + b654af3 commit 3a991e7
Show file tree
Hide file tree
Showing 27 changed files with 1,126 additions and 107 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@

## Unreleased Changes

### FEATURES

- `[ibc]`
- Implementation of the `ChanOpenAck`, `ChanOpenConfirm`, `ChanCloseInit`, and `ChanCloseConfirm` handlers ([#316])

### BUG FIXES:

- [relayer-cli]
- `[ibc]`
- Fix panic in conn open try when no connection id is provided ([#626])

- `[ibc-relayer-cli]`
- Fix wrong acks sent with `tx raw packet-ack` in a 3-chain setup ([#614])


[#316]: https://github.com/informalsystems/ibc-rs/issues/316
[#614]: https://github.com/informalsystems/ibc-rs/issues/614
[#626]: https://github.com/informalsystems/ibc-rs/issues/626

## v0.1.0
*February 4, 2021*
Expand Down
3 changes: 1 addition & 2 deletions modules/src/ics03_connection/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,8 @@ impl ConnectionEnd {
}

/// Setter for the `version` field.
/// TODO: A ConnectionEnd should only store one version.
pub fn set_version(&mut self, new_version: Version) {
self.versions.insert(0, new_version)
self.versions = vec![new_version];
}

/// Helper function to compare the counterparty of this end with another counterparty.
Expand Down
6 changes: 4 additions & 2 deletions modules/src/ics03_connection/handler/conn_open_try.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ pub(crate) fn process(
.ok_or(Kind::NoCommonVersion)?,
);

assert_eq!(new_connection_end.versions().len(), 1);

output.log("success: connection verification passed");

let result = ConnectionResult {
Expand Down Expand Up @@ -124,9 +126,9 @@ mod tests {
want_pass: bool,
}

let host_chain_height = Height::new(1, 35);
let host_chain_height = Height::new(0, 35);
let context = MockContext::new(
ChainId::new("mockgaia".to_string(), 1),
ChainId::new("mockgaia".to_string(), 0),
HostType::Mock,
5,
host_chain_height,
Expand Down
9 changes: 9 additions & 0 deletions modules/src/ics03_connection/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,13 @@ pub mod test_util {
}),
}
}
pub fn get_dummy_counterparty_ics26() -> RawCounterparty {
RawCounterparty {
client_id: "9999-mock-0".to_string(),
connection_id: "defaultConnection-0".to_string(),
prefix: Some(MerklePrefix {
key_prefix: b"ibc".to_vec(),
}),
}
}
}
24 changes: 24 additions & 0 deletions modules/src/ics03_connection/msgs/conn_open_ack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,30 @@ pub mod test_util {
signer: get_dummy_bech32_account(),
}
}

pub fn get_dummy_msg_conn_open_ack_ics26(
proof_height: u64,
consensus_height: u64,
) -> RawMsgConnectionOpenAck {
RawMsgConnectionOpenAck {
connection_id: "defaultConnection-0".to_string(),
counterparty_connection_id: "defaultConnection-0".to_string(),
proof_try: get_dummy_proof(),
proof_height: Some(Height {
revision_number: 0,
revision_height: proof_height,
}),
proof_consensus: get_dummy_proof(),
consensus_height: Some(Height {
revision_number: 0,
revision_height: consensus_height,
}),
client_state: None,
proof_client: vec![],
version: Some(Version::default().into()),
signer: get_dummy_bech32_account(),
}
}
}

#[cfg(test)]
Expand Down
10 changes: 10 additions & 0 deletions modules/src/ics03_connection/msgs/conn_open_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub mod test_util {
use ibc_proto::ibc::core::connection::v1::MsgConnectionOpenInit as RawMsgConnectionOpenInit;

use crate::ics03_connection::msgs::test_util::get_dummy_counterparty;
use crate::ics03_connection::msgs::test_util::get_dummy_counterparty_ics26;
use crate::ics03_connection::version::Version;
use crate::test_utils::get_dummy_bech32_account;

Expand All @@ -118,6 +119,15 @@ pub mod test_util {
signer: get_dummy_bech32_account(),
}
}
pub fn get_dummy_msg_conn_open_init_ics26() -> RawMsgConnectionOpenInit {
RawMsgConnectionOpenInit {
client_id: "9999-mock-0".to_string(),
counterparty: Some(get_dummy_counterparty_ics26()),
version: Some(Version::default().into()),
delay_period: 0,
signer: get_dummy_bech32_account(),
}
}
}

#[cfg(test)]
Expand Down
29 changes: 29 additions & 0 deletions modules/src/ics03_connection/msgs/conn_open_try.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ impl From<MsgConnectionOpenTry> for RawMsgConnectionOpenTry {
#[cfg(test)]
pub mod test_util {
use crate::ics03_connection::msgs::test_util::get_dummy_counterparty;
use crate::ics03_connection::msgs::test_util::get_dummy_counterparty_ics26;
use crate::ics03_connection::version::get_compatible_versions;
use crate::test_utils::{get_dummy_bech32_account, get_dummy_proof};
use ibc_proto::ibc::core::client::v1::Height;
Expand Down Expand Up @@ -253,6 +254,34 @@ pub mod test_util {
signer: get_dummy_bech32_account(),
}
}
pub fn get_dummy_msg_conn_open_try_ics26(
proof_height: u64,
consensus_height: u64,
) -> RawMsgConnectionOpenTry {
RawMsgConnectionOpenTry {
client_id: "9999-mock-0".to_string(),
previous_connection_id: "defaultConnection-0".to_string(),
client_state: None,
counterparty: Some(get_dummy_counterparty_ics26()),
delay_period: 0,
counterparty_versions: get_compatible_versions()
.iter()
.map(|v| v.clone().into())
.collect(),
proof_init: get_dummy_proof(),
proof_height: Some(Height {
revision_number: 0,
revision_height: proof_height,
}),
proof_consensus: get_dummy_proof(),
consensus_height: Some(Height {
revision_number: 0,
revision_height: consensus_height,
}),
proof_client: vec![],
signer: get_dummy_bech32_account(),
}
}
}

#[cfg(test)]
Expand Down
20 changes: 20 additions & 0 deletions modules/src/ics04_channel/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ impl ChannelEnd {
pub fn set_state(&mut self, s: State) {
self.state = s;
}
pub fn set_version(&mut self, v: String) {
self.version = v;
}

pub fn state(&self) -> &State {
&self.state
Expand Down Expand Up @@ -350,6 +353,13 @@ pub mod test_util {
channel_id: "channel24".into(),
}
}
/// Returns a dummy `RawCounterparty`, for testing only!
pub fn get_dummy_raw_counterparty_ics26() -> RawCounterparty {
RawCounterparty {
port_id: "port".into(),
channel_id: "defaultChannel-0".into(),
}
}

/// Returns a dummy `RawCounterparty`, for testing only!
pub fn get_another_dummy_raw_counterparty() -> RawCounterparty {
Expand All @@ -369,6 +379,16 @@ pub mod test_util {
version: "ics20".to_string(), // The version is not validated.
}
}
/// Returns a dummy `RawChannel`, for testing only!
pub fn get_dummy_raw_channel_end_ics26() -> RawChannel {
RawChannel {
state: 1,
ordering: 1,
counterparty: Some(get_dummy_raw_counterparty_ics26()),
connection_hops: vec!["defaultConnection-0".to_string()],
version: "ics20".to_string(), // The version is not validated.
}
}

/// Returns a dummy `RawChannel`, for testing only!
pub fn get_dummy_raw_channel_end_with_counterparty() -> RawChannel {
Expand Down
4 changes: 1 addition & 3 deletions modules/src/ics04_channel/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ pub trait ChannelReader {
height: Height,
) -> Option<AnyConsensusState>;

fn port_capability(&self, port_id: &PortId) -> Option<Capability>;

fn capability_authentification(&self, port_id: &PortId, cap: &Capability) -> bool;
fn authenticated_capability(&self, port_id: &PortId) -> Result<Capability, Error>;
}

/// A context supplying all the necessary write-only dependencies (i.e., storage writing facility)
Expand Down
11 changes: 10 additions & 1 deletion modules/src/ics04_channel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub enum Kind {
#[error("Undefined counterparty connection for {0}")]
UndefinedConnectionCounterparty(ConnectionId),

#[error("Channel chain verification fails")]
#[error("Channel chain verification fails on ChannelOpenTry for ChannelOpenInit")]
FailedChanneOpenTryVerification,

#[error("No client state associated with the channel")]
Expand All @@ -98,6 +98,15 @@ pub enum Kind {

#[error("Client not found in chan open verification")]
ClientNotFound,

#[error("Channel is in state {0} which is invalid")]
InvalidChannelState(ChannelId),

#[error("Channel is in state {0}")]
ChannelAlreadyClosed(ChannelId),

#[error("Channel chain verification fails on ChannelOpenAck for ChannelOpenTry")]
FailedChanneOpenAckVerification,
}

impl Kind {
Expand Down
12 changes: 9 additions & 3 deletions modules/src/ics04_channel/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ use crate::ics04_channel::msgs::ChannelMsg;
use crate::ics05_port::capabilities::Capability;
use crate::ics24_host::identifier::{ChannelId, PortId};

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;

mod verify;
#[derive(Clone, Debug)]
pub struct ChannelResult {
Expand All @@ -28,8 +33,9 @@ where
match msg {
ChannelMsg::ChannelOpenInit(msg) => chan_open_init::process(ctx, msg),
ChannelMsg::ChannelOpenTry(msg) => chan_open_try::process(ctx, msg),
// ChannelMsg::ChannelOpenAck(msg) => chan_open_ack::process(ctx, msg),
// ChannelMsg::ChannelOpenConfirm(msg) => chan_open_confirm::process(ctx, msg),
_ => panic!(),
ChannelMsg::ChannelOpenAck(msg) => chan_open_ack::process(ctx, msg),
ChannelMsg::ChannelOpenConfirm(msg) => chan_open_confirm::process(ctx, msg),
ChannelMsg::ChannelCloseInit(msg) => chan_close_init::process(ctx, msg),
ChannelMsg::ChannelCloseConfirm(msg) => chan_close_confirm::process(ctx, msg),
}
}
97 changes: 97 additions & 0 deletions modules/src/ics04_channel/handler/chan_close_confirm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//! Protocol logic specific to ICS4 messages of type `MsgChannelCloseInit`.
use crate::handler::{HandlerOutput, HandlerResult};
use crate::ics03_connection::connection::State as ConnectionState;
use crate::ics04_channel::channel::State;
use crate::ics04_channel::context::ChannelReader;
use crate::ics04_channel::error::{Error, Kind};
use crate::ics04_channel::events::Attributes;
use crate::ics04_channel::handler::verify::verify_proofs;
use crate::ics04_channel::handler::ChannelResult;
use crate::ics04_channel::msgs::chan_close_confirm::MsgChannelCloseConfirm;
use crate::{
events::IBCEvent,
ics04_channel::channel::{ChannelEnd, Counterparty},
};
use Kind::ConnectionNotOpen;

pub(crate) fn process(
ctx: &dyn ChannelReader,
msg: MsgChannelCloseConfirm,
) -> HandlerResult<ChannelResult, Error> {
let mut output = HandlerOutput::builder();

// Retrieve the old channel end and validate it against the message.

let mut channel_end = ctx
.channel_end(&(msg.port_id().clone(), msg.channel_id().clone()))
.ok_or_else(|| Kind::ChannelNotFound.context(msg.channel_id().clone().to_string()))?;

// Validate that the channel end is in a state where it can be closed.
if channel_end.state_matches(&State::Closed) {
return Err(Kind::ChannelAlreadyClosed(msg.channel_id().clone()).into());
}

// Channel capabilities
let channel_cap = ctx.authenticated_capability(&msg.port_id().clone())?;

// An OPEN IBC connection running on the local (host) chain should exist.
if channel_end.connection_hops().len() != 1 {
return Err(Kind::InvalidConnectionHopsLength.into());
}
let conn = ctx
.connection_end(&channel_end.connection_hops()[0])
.ok_or_else(|| Kind::MissingConnection(channel_end.connection_hops()[0].clone()))?;
if !conn.state_matches(&ConnectionState::Open) {
return Err(ConnectionNotOpen(channel_end.connection_hops()[0].clone()).into());
}

// Proof verification in two steps:
// 1. Setup: build the Channel as we expect to find it on the other party.

let expected_counterparty =
Counterparty::new(msg.port_id().clone(), Some(msg.channel_id().clone()));

let counterparty = conn.counterparty();
let ccid = counterparty.connection_id().ok_or_else(|| {
Kind::UndefinedConnectionCounterparty(channel_end.connection_hops()[0].clone())
})?;

let expected_connection_hops = vec![ccid.clone()];

let expected_channel_end = ChannelEnd::new(
State::Closed,
*channel_end.ordering(),
expected_counterparty,
expected_connection_hops,
channel_end.version(),
);

verify_proofs(
ctx,
&channel_end,
&conn,
&expected_channel_end,
&msg.proofs(),
)
.map_err(|e| Kind::FailedChanneOpenTryVerification.context(e))?;

output.log("success: channel close confirm ");

// Transition the channel end to the new state & pick a version.
channel_end.set_state(State::Closed);

let result = ChannelResult {
port_id: msg.port_id().clone(),
channel_id: Some(msg.channel_id().clone()),
channel_cap,
channel_end,
};

let event_attributes = Attributes {
channel_id: Some(msg.channel_id().clone()),
..Default::default()
};
output.emit(IBCEvent::CloseConfirmChannel(event_attributes.into()));

Ok(output.with_result(result))
}
Loading

0 comments on commit 3a991e7

Please sign in to comment.