diff --git a/core/src/ibc/connection_03/manager.rs b/core/src/ibc/connection_03/manager.rs
index 44a5487f45..cbc70b1a12 100644
--- a/core/src/ibc/connection_03/manager.rs
+++ b/core/src/ibc/connection_03/manager.rs
@@ -15,7 +15,7 @@
// along with this program. If not, see .
use super::path as connection_path;
-use super::types::{CommitmentPrefix, Identifier};
+use super::types::{CommitmentPrefix, CommitmentProof, Identifier};
use crate::ibc;
use crate::ibc::connection_03::client_connections_path;
use crate::ibc::connection_03::types::{ConnectionEnd, ConnectionIdentifiersInClient, ConnectionState};
@@ -24,6 +24,11 @@ use rlp::{Encodable, Rlp};
#[derive(Default)]
pub struct Manager {}
+// FIXME: this will be changed after implementing Vector commitment
+fn get_commiment_prefix() -> String {
+ "".to_owned()
+}
+
impl Manager {
pub fn new() -> Self {
Manager {}
@@ -55,6 +60,105 @@ impl Manager {
Ok(())
}
+ // We all following ICS spec.
+ #[allow(clippy::too_many_arguments)]
+ pub fn handle_open_try(
+ &self,
+ ctx: &mut dyn ibc::Context,
+ desired_identifier: Identifier,
+ counterparty_connection_identifier: Identifier,
+ counterparty_prefix: CommitmentPrefix,
+ counterparty_client_identifier: Identifier,
+ client_identifier: Identifier,
+ proof_init: CommitmentProof,
+ proof_consensus: CommitmentProof,
+ proof_height: u64,
+ consensus_height: u64,
+ ) -> Result<(), String> {
+ let current_height = ctx.get_current_height();
+ if consensus_height > current_height {
+ return Err(format!(
+ "Consensus height {} is greater than current height {}",
+ consensus_height, current_height
+ ))
+ }
+ let expected = ConnectionEnd {
+ state: ConnectionState::INIT,
+ counterparty_connection_identifier: desired_identifier.clone(),
+ counterparty_prefix: get_commiment_prefix(),
+ client_identifier: counterparty_client_identifier.clone(),
+ counterparty_client_identifier: client_identifier.clone(),
+ };
+
+ let connection = ConnectionEnd {
+ state: ConnectionState::TRYOPEN,
+ counterparty_connection_identifier: counterparty_client_identifier.clone(),
+ counterparty_prefix: counterparty_prefix.clone(),
+ client_identifier: client_identifier.clone(),
+ counterparty_client_identifier: counterparty_client_identifier.clone(),
+ };
+
+ self.verify_connection_state(ctx, &connection, proof_height, proof_init, desired_identifier.clone(), &expected);
+
+ if let Some(previous_connection_end) = self.query(ctx, &desired_identifier) {
+ let expected_init = ConnectionEnd {
+ state: ConnectionState::INIT,
+ counterparty_connection_identifier,
+ counterparty_prefix,
+ client_identifier,
+ counterparty_client_identifier,
+ };
+ if previous_connection_end != expected_init {
+ return Err(format!(
+ "Invalid previous connection status: previous: {:?}, expected: {:?}",
+ previous_connection_end, expected_init
+ ))
+ }
+ }
+
+ let kv_store = ctx.get_kv_store();
+ kv_store.set(&connection_path(&desired_identifier), &connection.rlp_bytes());
+ Ok(())
+ }
+
+ fn query(&self, ctx: &mut dyn ibc::Context, identifier: &str) -> Option {
+ let kv_store = ctx.get_kv_store();
+
+ let path = connection_path(&identifier);
+ if kv_store.has(&path) {
+ let raw = kv_store.get(&path);
+ let connection_end = rlp::decode(&raw).expect("Only the connection code can save the code");
+ return Some(connection_end)
+ }
+
+ None
+ }
+
+ fn verify_connection_state(
+ &self,
+ ctx: &mut dyn ibc::Context,
+ connection: &ConnectionEnd,
+ proof_height: u64,
+ proof: CommitmentProof,
+ connection_identifier: Identifier,
+ connection_end: &ConnectionEnd,
+ ) -> bool {
+ // check values in the connection_end
+ let path = format!("connections/{}", connection_identifier);
+ self.client_verify_membership(proof_height, proof, path, &rlp::encode(connection_end))
+ }
+
+ fn client_verify_membership(
+ &self,
+ _height: u64,
+ _commitment_proof: CommitmentProof,
+ _path: String,
+ _value: &[u8],
+ ) -> bool {
+ // FIXME
+ true
+ }
+
fn add_connection_to_client(
&self,
ctx: &mut dyn ibc::Context,
diff --git a/core/src/ibc/connection_03/types.rs b/core/src/ibc/connection_03/types.rs
index 6622242f3f..a2a041d4d2 100644
--- a/core/src/ibc/connection_03/types.rs
+++ b/core/src/ibc/connection_03/types.rs
@@ -45,6 +45,8 @@ impl rlp::Decodable for ConnectionState {
// FIXME: current commitment_23::Prefix is too generic.
pub type CommitmentPrefix = String;
+// FIXME: This type will be replaced after commitment code changed.
+pub type CommitmentProof = String;
pub type Identifier = String;
#[derive(RlpEncodable, RlpDecodable, PartialEq, Debug)]
diff --git a/core/src/ibc/transaction_handler/datagrams.rs b/core/src/ibc/transaction_handler/datagrams.rs
index cd013524b3..5b8e128bc5 100644
--- a/core/src/ibc/transaction_handler/datagrams.rs
+++ b/core/src/ibc/transaction_handler/datagrams.rs
@@ -22,6 +22,7 @@ enum DatagramTag {
CreateClient = 1,
UpdateClient = 2,
ConnOpenInit = 3,
+ ConnOpenTry = 4,
}
impl Encodable for DatagramTag {
@@ -37,6 +38,7 @@ impl Decodable for DatagramTag {
1 => Ok(DatagramTag::CreateClient),
2 => Ok(DatagramTag::UpdateClient),
3 => Ok(DatagramTag::ConnOpenInit),
+ 4 => Ok(DatagramTag::ConnOpenTry),
_ => Err(DecoderError::Custom("Unexpected DatagramTag Value")),
}
}
@@ -60,6 +62,17 @@ pub enum Datagram {
client_identifier: String,
counterparty_client_identifier: String,
},
+ ConnOpenTry {
+ desired_identifier: String,
+ counterparty_connection_identifier: String,
+ counterparty_prefix: String,
+ counterparty_client_identifier: String,
+ client_identifier: String,
+ proof_init: String,
+ proof_consensus: String,
+ proof_height: u64,
+ consensus_height: u64,
+ },
}
impl Encodable for Datagram {
@@ -93,6 +106,29 @@ impl Encodable for Datagram {
.append(client_identifier)
.append(counterparty_client_identifier);
}
+ Datagram::ConnOpenTry {
+ desired_identifier,
+ counterparty_connection_identifier,
+ counterparty_prefix,
+ counterparty_client_identifier,
+ client_identifier,
+ proof_init,
+ proof_consensus,
+ proof_height,
+ consensus_height,
+ } => {
+ s.begin_list(10);
+ s.append(&DatagramTag::ConnOpenTry)
+ .append(desired_identifier)
+ .append(counterparty_connection_identifier)
+ .append(counterparty_prefix)
+ .append(counterparty_client_identifier)
+ .append(client_identifier)
+ .append(proof_init)
+ .append(proof_consensus)
+ .append(proof_height)
+ .append(consensus_height);
+ }
};
}
}
@@ -144,6 +180,26 @@ impl Decodable for Datagram {
counterparty_client_identifier: rlp.val_at(5)?,
})
}
+ DatagramTag::ConnOpenTry => {
+ let item_count = rlp.item_count()?;
+ if item_count != 10 {
+ return Err(DecoderError::RlpInvalidLength {
+ expected: 10,
+ got: item_count,
+ })
+ }
+ Ok(Datagram::ConnOpenTry {
+ desired_identifier: rlp.val_at(1)?,
+ counterparty_connection_identifier: rlp.val_at(2)?,
+ counterparty_prefix: rlp.val_at(3)?,
+ counterparty_client_identifier: rlp.val_at(4)?,
+ client_identifier: rlp.val_at(5)?,
+ proof_init: rlp.val_at(6)?,
+ proof_consensus: rlp.val_at(7)?,
+ proof_height: rlp.val_at(8)?,
+ consensus_height: rlp.val_at(9)?,
+ })
+ }
}
}
}
diff --git a/core/src/ibc/transaction_handler/mod.rs b/core/src/ibc/transaction_handler/mod.rs
index d4d8c656b9..3f050267c4 100644
--- a/core/src/ibc/transaction_handler/mod.rs
+++ b/core/src/ibc/transaction_handler/mod.rs
@@ -65,6 +65,34 @@ pub fn execute(
)
.map_err(|err| RuntimeError::IBC(format!("ConnOpenInit: {}", err)).into())
}
+ Datagram::ConnOpenTry {
+ desired_identifier,
+ counterparty_connection_identifier,
+ counterparty_prefix,
+ counterparty_client_identifier,
+ client_identifier,
+ proof_init,
+ proof_consensus,
+ proof_height,
+ consensus_height,
+ } => {
+ let mut context = ibc_context::TopLevelContext::new(state, current_block_number);
+ let connection_manager = ibc_connection::Manager::new();
+ connection_manager
+ .handle_open_try(
+ &mut context,
+ desired_identifier,
+ counterparty_connection_identifier,
+ counterparty_prefix,
+ counterparty_client_identifier,
+ client_identifier,
+ proof_init,
+ proof_consensus,
+ proof_height,
+ consensus_height,
+ )
+ .map_err(|err| RuntimeError::IBC(format!("ConnOpenTry: {}", err)).into())
+ }
}
}