Skip to content

Commit

Permalink
feat: implement conn_open_confirm handler + test (#116)
Browse files Browse the repository at this point in the history
* feat: implement conn_open_confirm handler + test

* nit: add missing docstring for open()
  • Loading branch information
Farhad-Shabani authored Nov 14, 2024
1 parent 5e46372 commit a7c8036
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 30 deletions.
29 changes: 27 additions & 2 deletions cairo-contracts/packages/contracts/src/tests/connection.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ fn test_conn_open_ack_ok() {
.assert_conn_open_ack_event(
core.address,
conn_id_on_a.client_id,
CONNECTION_ID(0),
msg.conn_id_on_a,
conn_id_on_a.counterparty.client_id,
conn_id_on_a.counterparty.connection_id,
);
Expand All @@ -125,7 +125,15 @@ fn test_conn_open_confirm_ok() {
// Setup Essentials
// -----------------------------------------------------------

let (core, _, _, core_cfg, _, _, _) = setup();
let (core, _, _, core_cfg, _, _, mut spy) = setup();

// -----------------------------------------------------------
// Connection Open Try
// -----------------------------------------------------------

let msg = core_cfg.dummy_msg_conn_open_try();

core.conn_open_try(msg);

// -----------------------------------------------------------
// Connection Open Confirm
Expand All @@ -134,4 +142,21 @@ fn test_conn_open_confirm_ok() {
let msg = core_cfg.dummy_msg_conn_open_confirm();

core.conn_open_confirm(msg.clone());

// -----------------------------------------------------------
// Check Results
// -----------------------------------------------------------

let conn_id_on_b = core.connection_end(msg.conn_id_on_b.clone());

assert_eq!(conn_id_on_b.state(), @ConnectionState::Open);

spy
.assert_conn_open_confirm_event(
core.address,
conn_id_on_b.client_id,
msg.conn_id_on_b,
conn_id_on_b.counterparty.client_id,
conn_id_on_b.counterparty.connection_id,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ pub mod ChannelHandlerComponent {
@msg.chan_id_on_a,
chan_end_on_a
.clone()
.open_with_params(msg.chan_id_on_b.clone(), msg.version_on_b.clone())
.to_open_with_params(msg.chan_id_on_b.clone(), msg.version_on_b.clone())
);

self
Expand Down Expand Up @@ -377,7 +377,7 @@ pub mod ChannelHandlerComponent {

self
.write_channel_end(
@msg.port_id_on_b, @msg.chan_id_on_b, chan_end_on_b.clone().open()
@msg.port_id_on_b, @msg.chan_id_on_b, chan_end_on_b.clone().to_open()
);

self
Expand Down
6 changes: 3 additions & 3 deletions cairo-contracts/packages/core/src/channel/types.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::num::traits::Zero;
use starknet_ibc_core::channel::ChannelErrors;
use starknet_ibc_core::client::{Height, Timestamp, HeightPartialOrd, TimestampPartialOrd};
use starknet_ibc_core::commitment::{array_u8_into_array_u32, IntoArrayU32};
use starknet_ibc_core::host::{ClientId, ClientIdTrait, ChannelId, PortId, PortIdTrait, Sequence};
use starknet_ibc_core::host::{ClientId, ChannelId, PortId, PortIdTrait, Sequence};
use starknet_ibc_utils::ValidateBasic;

#[derive(Clone, Debug, Drop, Serde)]
Expand Down Expand Up @@ -130,7 +130,7 @@ pub impl ChannelEndImpl of ChannelEndTrait {
}

/// Consumes the channel end and returns a new channel end with the state set to open.
fn open(self: ChannelEnd) -> ChannelEnd {
fn to_open(self: ChannelEnd) -> ChannelEnd {
ChannelEnd {
state: ChannelState::Open,
ordering: self.ordering,
Expand All @@ -141,7 +141,7 @@ pub impl ChannelEndImpl of ChannelEndTrait {
}

/// Opens the channel end with the given counterparty channel ID and version.
fn open_with_params(
fn to_open_with_params(
self: ChannelEnd, couterparty_chan_id: ChannelId, version: AppVersion
) -> ChannelEnd {
ChannelEnd {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,16 @@ pub mod ConnectionEventEmitterComponent {
}

#[derive(Debug, Drop, starknet::Event)]
pub struct ConnOpenConfirmEvent {}
pub struct ConnOpenConfirmEvent {
#[key]
pub client_id_on_b: ClientId,
#[key]
pub connection_id_on_b: ConnectionId,
#[key]
pub client_id_on_a: ClientId,
#[key]
pub connection_id_on_a: ConnectionId,
}

#[generate_trait]
pub impl ConnectionEventEmitterImpl<
Expand Down Expand Up @@ -93,6 +102,21 @@ pub mod ConnectionEventEmitterComponent {
}
);
}

fn emit_conn_open_confirm_event(
ref self: ComponentState<TContractState>,
client_id_on_b: ClientId,
connection_id_on_b: ConnectionId,
client_id_on_a: ClientId,
connection_id_on_a: ConnectionId,
) {
self
.emit(
ConnOpenConfirmEvent {
client_id_on_b, connection_id_on_b, client_id_on_a, connection_id_on_a,
}
);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ pub mod ConnectionHandlerComponent {
use starknet::storage::{Map, Vec, VecTrait, MutableVecTrait};
use starknet_ibc_core::client::{ClientHandlerComponent, ClientContract, ClientContractTrait};
use starknet_ibc_core::connection::{
ConnectionEventEmitterComponent, IConnectionHandler, IConnectionQuery, MsgConnOpenConfirm,
MsgConnOpenInit, MsgConnOpenInitTrait, MsgConnOpenTry, MsgConnOpenTryTrait, MsgConnOpenAck,
ConnectionEnd, ConnectionEndTrait, ConnectionErrors
ConnectionEventEmitterComponent, IConnectionHandler, IConnectionQuery, MsgConnOpenInit,
MsgConnOpenInitTrait, MsgConnOpenTry, MsgConnOpenTryTrait, MsgConnOpenAck,
MsgConnOpenConfirm, ConnectionEnd, ConnectionEndTrait, ConnectionErrors
};
use starknet_ibc_core::host::{
ClientId, ConnectionId, ConnectionIdImpl, connection_path, client_connection_key,
connection_end_key
ClientId, ConnectionId, ConnectionIdImpl, PathPrefixZero, connection_path,
client_connection_key, connection_end_key
};
use starknet_ibc_utils::ValidateBasic;

Expand Down Expand Up @@ -61,7 +61,11 @@ pub mod ConnectionHandlerComponent {
self.conn_open_ack_execute(conn_end_on_a, msg);
}

fn conn_open_confirm(ref self: ComponentState<TContractState>, msg: MsgConnOpenConfirm) {}
fn conn_open_confirm(ref self: ComponentState<TContractState>, msg: MsgConnOpenConfirm) {
let conn_end_on_b = self.read_connection_end(@msg.conn_id_on_b);
self.conn_open_confirm_validate(conn_end_on_b.clone(), msg.clone());
self.conn_open_confirm_execute(conn_end_on_b, msg);
}
}

// -----------------------------------------------------------
Expand Down Expand Up @@ -241,7 +245,7 @@ pub mod ConnectionHandlerComponent {
self
.write_connection_end(
@msg.conn_id_on_a,
conn_end_on_a.clone().open_with_params(msg.conn_id_on_b.clone(), msg.version)
conn_end_on_a.clone().to_open_with_params(msg.conn_id_on_b.clone(), msg.version)
);

self
Expand All @@ -254,6 +258,66 @@ pub mod ConnectionHandlerComponent {
}
}

#[generate_trait]
pub(crate) impl ConnOpenConfirmImpl<
TContractState,
+HasComponent<TContractState>,
+Drop<TContractState>,
impl EventEmitter: ConnectionEventEmitterComponent::HasComponent<TContractState>,
impl ClientHandler: ClientHandlerComponent::HasComponent<TContractState>,
> of ConnOpenConfitmTrait<TContractState> {
fn conn_open_confirm_validate(
self: @ComponentState<TContractState>,
conn_end_on_b: ConnectionEnd,
msg: MsgConnOpenConfirm
) {
msg.validate_basic();

assert(conn_end_on_b.is_try_open(), ConnectionErrors::INVALID_CONNECTION_STATE);

let client = self.get_client(conn_end_on_b.client_id.client_type);

let client_sequence = conn_end_on_b.client_id.sequence;

client.verify_is_active(client_sequence);

client.verify_proof_height(@msg.proof_height_on_a, client_sequence);

let expected_conn_end_on_a = ConnectionEndTrait::open(
conn_end_on_b.counterparty.client_id.clone(),
conn_end_on_b.client_id.clone(),
msg.conn_id_on_b.clone(),
PathPrefixZero::zero(),
conn_end_on_b.version.clone(),
conn_end_on_b.delay_period
);

let path = conn_end_on_b.counterparty.prefix.prefix.clone()
+ connection_path(conn_end_on_b.counterparty.connection_id.clone());

client
.verify_membership(
client_sequence, path, expected_conn_end_on_a.into(), msg.proof_conn_end_on_a
);
}

fn conn_open_confirm_execute(
ref self: ComponentState<TContractState>,
conn_end_on_b: ConnectionEnd,
msg: MsgConnOpenConfirm
) {
self.write_connection_end(@msg.conn_id_on_b, conn_end_on_b.clone().to_open(),);

self
.emit_conn_open_confirm_event(
conn_end_on_b.client_id.clone(),
msg.conn_id_on_b.clone(),
conn_end_on_b.counterparty.client_id.clone(),
msg.conn_id_on_b
);
}
}

// -----------------------------------------------------------
// Connection Internal
// -----------------------------------------------------------
Expand Down Expand Up @@ -408,6 +472,21 @@ pub mod ConnectionHandlerComponent {
client_id_on_a, connection_id_on_a, client_id_on_b, connection_id_on_b
);
}

fn emit_conn_open_confirm_event(
ref self: ComponentState<TContractState>,
client_id_on_b: ClientId,
connection_id_on_b: ConnectionId,
client_id_on_a: ClientId,
connection_id_on_a: ConnectionId,
) {
let mut event_emitter = get_dep_component_mut!(ref self, EventEmitter);

event_emitter
.emit_conn_open_confirm_event(
client_id_on_b, connection_id_on_b, client_id_on_a, connection_id_on_a
);
}
}
}

12 changes: 10 additions & 2 deletions cairo-contracts/packages/core/src/connection/msgs.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,16 @@ pub impl MsgConnOpenAckValidateBasic of ValidateBasic<MsgConnOpenAck> {
}

#[derive(Clone, Debug, Drop, PartialEq, Serde)]
pub struct MsgConnOpenConfirm {}
pub struct MsgConnOpenConfirm {
pub conn_id_on_b: ConnectionId,
pub proof_conn_end_on_a: StateProof,
pub proof_height_on_a: Height,
}

impl MsgConnOpenConfirmValidateBasic of ValidateBasic<MsgConnOpenConfirm> {
fn validate_basic(self: @MsgConnOpenConfirm) {}
fn validate_basic(self: @MsgConnOpenConfirm) {
assert(!self.conn_id_on_b.is_zero(), ConnectionErrors::MISSING_CONNECTION_ID);
assert(self.proof_conn_end_on_a.is_non_zero(), ConnectionErrors::EMPTY_CONN_END_PROOF);
assert(self.proof_height_on_a.is_non_zero(), ConnectionErrors::ZERO_PROOF_HEIGHT);
}
}
Loading

0 comments on commit a7c8036

Please sign in to comment.