Skip to content

Commit

Permalink
First processing logic for ICS 03 (#160).
Browse files Browse the repository at this point in the history
  • Loading branch information
adizere committed Jul 29, 2020
1 parent 6548786 commit 9f42758
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 6 deletions.
88 changes: 88 additions & 0 deletions modules/src/ics03_connection/core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//! This module implements the core functions of ICS03, that is, message processing logic for
//! processing any kind of ICS3 connection handshake message.
//!
//! TODO: in its current state, this module is not compiled nor included in the module tree.
use std::collections::HashMap;

use crate::ics03_connection::connection::ConnectionEnd;
use crate::ics03_connection::error::{Error, Kind};
use crate::ics03_connection::exported::{get_compatible_versions, State};
use crate::ics03_connection::msgs::{
ICS3Message, MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit,
MsgConnectionOpenTry,
};
use crate::ics24_host::identifier::ConnectionId;

/// General entry point for processing any type of message related to the ICS03 connection open
/// handshake protocol.
/// The `provable_store` parameter is a basic workaround, since there is no KV store yet.
/// TODO: the provable_store should be abstracted over, e.g., with a Keeper or similar mechanism.
pub fn process_conn_open_handshake_msg(
message: ICS3Message,
conn_id: &ConnectionId,
provable_store: &mut HashMap<String, ConnectionEnd>,
) -> Result<(), Error> {
// Preprocessing of the message. Basic validation was done already when creating the msg.
// Fetch from the store the already existing (if any) ConnectionEnd for this conn. identifier.
let current_conn_end = provable_store.get(conn_id.as_str());

// Process each message with the corresponding process_*_msg function.
// After processing a specific message, the outcome consists of a write set, i.e., a list of
// <key,value> pairs that must be updated in the provable store.
let new_ce = match message {
ICS3Message::ConnectionOpenInit(msg) => process_init_msg(msg, current_conn_end),
ICS3Message::ConnectionOpenTry(msg) => process_try_msg(msg, current_conn_end),
ICS3Message::ConnectionOpenAck(msg) => process_ack_msg(msg, current_conn_end),
ICS3Message::ConnectionOpenConfirm(msg) => process_confirm_msg(msg, current_conn_end),
}?;

provable_store.insert(conn_id.to_string(), new_ce);
// TODO: insert corresponding association into the client namespace of privateStore.

return Ok(());
}

/// Processing logic specific to messages of type `MsgConnectionOpenInit`.
fn process_init_msg(
msg: MsgConnectionOpenInit,
conn_end: Option<&ConnectionEnd>,
) -> Result<ConnectionEnd, Error> {
if conn_end.is_some() {
return Err(Kind::ConnectionExistsAlready
.context(msg.connection_id().to_string())
.into());
}

// TODO: consider adding `state` modifier to ConnectionEnd constructor.
let mut connection_end = ConnectionEnd::new(
msg.client_id().clone(),
msg.counterparty().clone(),
get_compatible_versions(),
)?;

connection_end.set_state(State::Init);

return Ok(connection_end);
}

fn process_try_msg(
_msg: MsgConnectionOpenTry,
_conn_end: Option<&ConnectionEnd>,
) -> Result<ConnectionEnd, Error> {
unimplemented!()
}

fn process_ack_msg(
_msg: MsgConnectionOpenAck,
_conn_end: Option<&ConnectionEnd>,
) -> Result<ConnectionEnd, Error> {
unimplemented!()
}

fn process_confirm_msg(
_msg: MsgConnectionOpenConfirm,
_conn_end: Option<&ConnectionEnd>,
) -> Result<ConnectionEnd, Error> {
unimplemented!()
}
3 changes: 3 additions & 0 deletions modules/src/ics03_connection/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ pub enum Kind {
#[error("connection state unknown")]
UnknownState,

#[error("connection exists (was initialized) already")]
ConnectionExistsAlready,

#[error("identifier error")]
IdentifierError,

Expand Down
18 changes: 18 additions & 0 deletions modules/src/ics03_connection/exported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ impl std::str::FromStr for State {
}
}

/// Function required by ICS 03. Returns the list of all possible versions that the connection
/// handshake protocol supports.
/// TODO: What are the precise values for the versions which this function returns? Perhaps encode the versions as constants.
pub fn get_compatible_versions() -> Vec<String> {
let mut result = Vec::with_capacity(1);
result[0] = String::from("test");

result
}

/// Function required by ICS 03. Returns one version out of the supplied list of versions, which the
/// connection handshake protocol prefers.
/// TODO: Fix this with proper code.
pub fn pick_version(candidates: Vec<String>) -> Option<&String> {
candidates.get(0)
}


#[cfg(test)]
mod tests {
use std::str::FromStr;
Expand Down
1 change: 1 addition & 0 deletions modules/src/ics03_connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub mod error;
pub mod events;
pub mod exported;
pub mod msgs;
pub mod core; // Core (message processing logic) of ICS 03.
62 changes: 56 additions & 6 deletions modules/src/ics03_connection/msgs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
//! Message definitions for the connection handshake datagrams.
//!
//! We define each of the four messages in the connection handshake protocol as a `struct`.
//! Each such message comprises the same fields as the datagrams defined in ICS03 English spec:
//! https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics.
//!
//! One departure from ICS03 is that we abstract the three counterparty fields (connection id,
//! prefix, and client id) into a single field of type `Counterparty`; this applies to messages
//! `MsgConnectionOpenInit` and `MsgConnectionOpenTry`.
//!
//! Another difference to ICS03 specs is that each message comprises an additional field called
//! `signer` which is specific to Cosmos-SDK.
//! TODO: Separate the Cosmos-SDK specific functionality from canonical ICS types.
#![allow(clippy::too_many_arguments)]
use crate::ics03_connection::connection::{validate_version, validate_versions, Counterparty};
use crate::ics03_connection::error::{Error, Kind};
Expand All @@ -9,8 +23,29 @@ use crate::tx_msg::Msg;
use serde_derive::{Deserialize, Serialize};
use tendermint::account::Id as AccountId;

/// Message type for the `MsgConnectionOpenInit` message.
pub const TYPE_MSG_CONNECTION_OPEN_INIT: &str = "connection_open_init";

/// Message type for the `MsgConnectionOpenTry` message.
pub const TYPE_MSG_CONNECTION_OPEN_TRY: &str = "connection_open_try";

/// Message type for the `MsgConnectionOpenAck` message.
pub const TYPE_MSG_CONNECTION_OPEN_ACK: &str = "connection_open_ack";

/// Message type for the `MsgConnectionOpenConfirm` message.
pub const TYPE_MSG_CONNECTION_OPEN_CONFIRM: &str = "connection_open_confirm";


pub enum ICS3Message {
ConnectionOpenInit(MsgConnectionOpenInit),
ConnectionOpenTry(MsgConnectionOpenTry),
ConnectionOpenAck(MsgConnectionOpenAck),
ConnectionOpenConfirm(MsgConnectionOpenConfirm),
}

///
/// Message definition `MsgConnectionOpenInit` (i.e., the `ConnOpenInit` datagram).
///
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MsgConnectionOpenInit {
connection_id: ConnectionId,
Expand Down Expand Up @@ -44,6 +79,18 @@ impl MsgConnectionOpenInit {
signer,
})
}

pub fn connection_id(&self) -> &ConnectionId {
&self.connection_id
}

pub fn client_id(&self) -> &ClientId {
&self.client_id
}

pub fn counterparty(&self) -> &Counterparty {
&self.counterparty
}
}

impl Msg for MsgConnectionOpenInit {
Expand Down Expand Up @@ -71,8 +118,9 @@ impl Msg for MsgConnectionOpenInit {
}
}

pub const TYPE_MSG_CONNECTION_OPEN_TRY: &str = "connection_open_try";

///
/// Message definition `MsgConnectionOpenTry` (i.e., `ConnOpenTry` datagram).
///
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MsgConnectionOpenTry {
connection_id: ConnectionId,
Expand Down Expand Up @@ -146,8 +194,9 @@ impl Msg for MsgConnectionOpenTry {
}
}

pub const TYPE_MSG_CONNECTION_OPEN_ACK: &str = "connection_open_ack";

///
/// Message definition `MsgConnectionOpenAck` (i.e., `ConnOpenAck` datagram).
///
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MsgConnectionOpenAck {
connection_id: ConnectionId,
Expand Down Expand Up @@ -205,8 +254,9 @@ impl Msg for MsgConnectionOpenAck {
}
}

pub const TYPE_MSG_CONNECTION_OPEN_CONFIRM: &str = "connection_open_confirm";

///
/// Message definition for `MsgConnectionOpenConfirm` (i.e., `ConnOpenConfirm` datagram).
///
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MsgConnectionOpenConfirm {
connection_id: ConnectionId,
Expand Down

0 comments on commit 9f42758

Please sign in to comment.