Skip to content
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
57 changes: 50 additions & 7 deletions core/src/ibc/connection_03/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::ibc;
use crate::ibc::commitment_23::types::{get_commiment_prefix, CommitmentPrefix, CommitmentProof};
use crate::ibc::connection_03::client_connections_path;
use crate::ibc::connection_03::types::{ConnectionEnd, ConnectionIdentifiersInClient, ConnectionState};
use primitives::Bytes;
use rlp::{Encodable, Rlp};

pub struct Manager<'a> {
Expand Down Expand Up @@ -67,8 +68,8 @@ impl<'a> Manager<'a> {
counterparty_prefix: CommitmentPrefix,
counterparty_client_identifier: Identifier,
client_identifier: Identifier,
proof_init: Vec<u8>,
proof_consensus: Vec<u8>,
proof_init: Bytes,
proof_consensus: Bytes,
proof_height: u64,
consensus_height: u64,
) -> Result<(), String> {
Expand All @@ -95,7 +96,9 @@ impl<'a> Manager<'a> {
counterparty_client_identifier: counterparty_client_identifier.clone(),
};

self.verify_connection_state(&connection, proof_height, proof_init, desired_identifier.clone(), &expected);
if !self.verify_connection_state(&connection, proof_height, proof_init, desired_identifier.clone(), &expected) {
return Err(format!("Counterparty chain's connection state verification fail. expected: {:?}", expected))
}

if let Some(previous_connection_end) = self.query(&desired_identifier) {
let expected_init = ConnectionEnd {
Expand All @@ -121,8 +124,8 @@ impl<'a> Manager<'a> {
pub fn handle_open_ack(
&mut self,
identifier: Identifier,
proof_try: Vec<u8>,
proof_consensus: Vec<u8>,
proof_try: Bytes,
proof_consensus: Bytes,
proof_height: u64,
consensus_height: u64,
) -> Result<(), String> {
Expand All @@ -147,7 +150,47 @@ impl<'a> Manager<'a> {
client_identifier: connection.counterparty_client_identifier.clone(),
counterparty_client_identifier: connection.client_identifier.clone(),
};
self.verify_connection_state(&connection, proof_height, proof_try, identifier.clone(), &expected_connection);

if !self.verify_connection_state(&connection, proof_height, proof_try, identifier.clone(), &expected_connection)
{
return Err(format!(
"Counterparty chain's connection state verification fail. expected: {:?}",
expected_connection
))
}

connection.state = ConnectionState::OPEN;
let kv_store = self.ctx.get_kv_store_mut();
let path = connection_path(&identifier);
kv_store.set(&path, &connection.rlp_bytes());

Ok(())
}

pub fn handle_open_confirm(
&mut self,
identifier: Identifier,
proof_ack: Bytes,
proof_height: u64,
) -> Result<(), String> {
let mut connection = self
.query(&identifier)
.ok_or_else(|| format!("Cannot find connection with the identifier: {}", identifier))?;
if connection.state != ConnectionState::TRYOPEN {
return Err(format!("Invalid connection state expected TRYOPEN but found {:?}", connection.state))
}

let expected = ConnectionEnd {
state: ConnectionState::OPEN,
counterparty_connection_identifier: identifier.clone(),
counterparty_prefix: get_commiment_prefix(),
client_identifier: connection.counterparty_client_identifier.clone(),
counterparty_client_identifier: connection.client_identifier.clone(),
};

if !self.verify_connection_state(&connection, proof_height, proof_ack, identifier.clone(), &expected) {
return Err(format!("Counterparty chain's connection state verification fail. expected: {:?}", expected))
}

connection.state = ConnectionState::OPEN;
let kv_store = self.ctx.get_kv_store_mut();
Expand All @@ -174,7 +217,7 @@ impl<'a> Manager<'a> {
&mut self,
connection: &ConnectionEnd,
proof_height: u64,
proof: Vec<u8>,
proof: Bytes,
connection_identifier: Identifier,
connection_end: &ConnectionEnd,
) -> bool {
Expand Down
4 changes: 2 additions & 2 deletions core/src/ibc/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::kv_store::{KVStore, Path};
use ccrypto::blake256;
use cstate::{TopLevelState, TopState, TopStateView};
use merkle_trie::proof::{CryptoProof, CryptoProofUnit};
use primitives::H256;
use primitives::{Bytes, H256};
use rlp::RlpStream;

pub trait Context {
Expand Down Expand Up @@ -70,7 +70,7 @@ impl<'a> TopLevelKVStore<'a> {
}

impl<'a> KVStore for TopLevelKVStore<'a> {
fn get(&self, path: Path) -> Vec<u8> {
fn get(&self, path: Path) -> Bytes {
let key = TopLevelKVStore::key(path);
self.state.ibc_data(&key).expect("Get key").expect("Data empty").into()
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/ibc/kv_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use merkle_trie::proof::{CryptoProof, CryptoProofUnit};
use primitives::H256;
use primitives::{Bytes, H256};

pub type Path<'a> = &'a str;

// An abstraction of state db that will be provided as a environment for the ICS handler.
pub trait KVStore {
fn get(&self, path: Path) -> Vec<u8>;
fn get(&self, path: Path) -> Bytes;
fn has(&self, path: Path) -> bool;
fn set(&mut self, path: Path, value: &[u8]);
fn delete(&mut self, path: Path);
Expand Down
100 changes: 93 additions & 7 deletions core/src/ibc/transaction_handler/datagrams.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use primitives::Bytes;
use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};

#[repr(u8)]
Expand All @@ -24,6 +25,7 @@ enum DatagramTag {
ConnOpenInit = 3,
ConnOpenTry = 4,
ConnOpenAck = 5,
ConnOpenConfirm = 6,
}

impl Encodable for DatagramTag {
Expand All @@ -41,6 +43,7 @@ impl Decodable for DatagramTag {
3 => Ok(DatagramTag::ConnOpenInit),
4 => Ok(DatagramTag::ConnOpenTry),
5 => Ok(DatagramTag::ConnOpenAck),
6 => Ok(DatagramTag::ConnOpenConfirm),
_ => Err(DecoderError::Custom("Unexpected DatagramTag Value")),
}
}
Expand All @@ -51,12 +54,12 @@ pub enum Datagram {
CreateClient {
id: String,
kind: u8,
consensus_state: Vec<u8>,
data: Vec<u8>,
consensus_state: Bytes,
data: Bytes,
},
UpdateClient {
id: String,
header: Vec<u8>,
header: Bytes,
},
ConnOpenInit {
identifier: String,
Expand All @@ -71,18 +74,23 @@ pub enum Datagram {
counterparty_prefix: String,
counterparty_client_identifier: String,
client_identifier: String,
proof_init: Vec<u8>,
proof_consensus: Vec<u8>,
proof_init: Bytes,
proof_consensus: Bytes,
proof_height: u64,
consensus_height: u64,
},
ConnOpenAck {
identifier: String,
proof_try: Vec<u8>,
proof_consensus: Vec<u8>,
proof_try: Bytes,
proof_consensus: Bytes,
proof_height: u64,
consensus_height: u64,
},
ConnOpenConfirm {
identifier: String,
proof_ack: Bytes,
proof_height: u64,
},
}

impl Encodable for Datagram {
Expand Down Expand Up @@ -160,6 +168,14 @@ impl Encodable for Datagram {
.append(proof_height)
.append(consensus_height);
}
Datagram::ConnOpenConfirm {
identifier,
proof_ack,
proof_height,
} => {
s.begin_list(4);
s.append(&DatagramTag::ConnOpenConfirm).append(identifier).append(proof_ack).append(proof_height);
}
};
}
}
Expand Down Expand Up @@ -248,6 +264,76 @@ impl Decodable for Datagram {
consensus_height: rlp.val_at(5)?,
})
}
DatagramTag::ConnOpenConfirm => {
let item_count = rlp.item_count()?;
if item_count != 4 {
return Err(DecoderError::RlpInvalidLength {
expected: 4,
got: item_count,
})
}
Ok(Datagram::ConnOpenConfirm {
identifier: rlp.val_at(1)?,
proof_ack: rlp.val_at(2)?,
proof_height: rlp.val_at(3)?,
})
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use rlp::{self, rlp_encode_and_decode_test};

#[test]
fn conn_open_init() {
let conn_open_init = Datagram::ConnOpenInit {
identifier: "identifier".to_owned(),
desired_counterparty_connection_identifier: "desired_counterparty_connection_identifier".to_owned(),
counterparty_prefix: "counterparty_prefix".to_owned(),
client_identifier: "client_identifier".to_owned(),
counterparty_client_identifier: "counterparty_client_identifier".to_owned(),
};
rlp_encode_and_decode_test!(conn_open_init);
}

#[test]
fn conn_open_try() {
let conn_open_try = Datagram::ConnOpenTry {
desired_identifier: "desired_identifier".to_owned(),
counterparty_connection_identifier: "counterparty_connection_identifier".to_owned(),
counterparty_prefix: "counterparty_prefix".to_owned(),
counterparty_client_identifier: "counterparty_client_identifier".to_owned(),
client_identifier: "client_identifier".to_owned(),
proof_init: b"proof_init".to_vec(),
proof_consensus: b"proof_consensus".to_vec(),
proof_height: 1,
consensus_height: 2,
};
rlp_encode_and_decode_test!(conn_open_try);
}

#[test]
fn conn_open_ack() {
let conn_open_ack = Datagram::ConnOpenAck {
identifier: "identifier".to_owned(),
proof_try: b"proof_try".to_vec(),
proof_consensus: b"proof_consensus".to_vec(),
proof_height: 1,
consensus_height: 2,
};
rlp_encode_and_decode_test!(conn_open_ack);
}

#[test]
fn conn_open_confirm() {
let conn_open_confirm = Datagram::ConnOpenConfirm {
identifier: "identifier".to_owned(),
proof_ack: b"proof_ack".to_vec(),
proof_height: 1,
};
rlp_encode_and_decode_test!(conn_open_confirm);
}
}
10 changes: 10 additions & 0 deletions core/src/ibc/transaction_handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ pub fn execute(
.handle_open_ack(identifier, proof_try, proof_consensus, proof_height, consensus_height)
.map_err(|err| RuntimeError::IBC(format!("ConnOpenAck: {}", err)).into())
}
Datagram::ConnOpenConfirm {
identifier,
proof_ack,
proof_height,
} => {
let mut connection_manager = ibc_connection::Manager::new(&mut context);
connection_manager
.handle_open_confirm(identifier, proof_ack, proof_height)
.map_err(|err| RuntimeError::IBC(format!("ConnOpenConfirm: {}", err)).into())
}
}
}

Expand Down