Skip to content

Commit

Permalink
tests: add some channel handler component tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Farhad-Shabani committed Sep 13, 2024
1 parent 20ae040 commit a4f244a
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 22 deletions.
47 changes: 38 additions & 9 deletions cairo-contracts/packages/core/src/channel/components/handler.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ pub mod ChannelHandlerComponent {
use starknet_ibc_core::client::{ClientHandlerComponent, ClientContractTrait, StatusTrait};
use starknet_ibc_core::host::{
PortId, PortIdTrait, ChannelId, ChannelIdTrait, Sequence, channel_end_key, receipt_key,
commitment_path
ack_key, commitment_path
};
use starknet_ibc_core::router::{RouterHandlerComponent, IRouter};
use starknet_ibc_utils::{ValidateBasicTrait, ComputeKeyTrait};

#[storage]
struct Storage {
pub channel_ends: Map<felt252, ChannelEnd>,
pub packet_receipts: Map<felt252, Receipt>,
pub channel_ends: Map<felt252, Option<ChannelEnd>>,
pub packet_receipts: Map<felt252, Option<Receipt>>,
pub packet_acks: Map<felt252, ByteArray>,
}

Expand Down Expand Up @@ -120,10 +120,12 @@ pub mod ChannelHandlerComponent {

match chan_end_on_b.ordering {
ChannelOrdering::Unordered => {
let _receipt = self
.read_packet_receipt(
let ack = self
.read_packet_ack(
@msg.packet.port_id_on_a, @msg.packet.chan_id_on_a, @msg.packet.seq_on_a
);

assert(ack.len() == 0, ChannelErrors::ACK_ALREADY_EXISTS);
},
ChannelOrdering::Ordered => {}
};
Expand Down Expand Up @@ -158,17 +160,30 @@ pub mod ChannelHandlerComponent {
fn read_channel_end(
self: @ComponentState<TContractState>, port_id: @PortId, channel_id: @ChannelId
) -> ChannelEnd {
self.channel_ends.read(channel_end_key(port_id, channel_id))
let maybe_chan_end = self.channel_ends.read(channel_end_key(port_id, channel_id));

assert(maybe_chan_end.is_some(), ChannelErrors::MISSING_CHANNEL_END);

maybe_chan_end.unwrap()
}

fn read_packet_receipt(
self: @ComponentState<TContractState>,
port_id: @PortId,
channel_id: @ChannelId,
sequence: @Sequence
) -> Receipt {
) -> Option<Receipt> {
self.packet_receipts.read(receipt_key(port_id, channel_id, sequence))
}

fn read_packet_ack(
self: @ComponentState<TContractState>,
port_id: @PortId,
channel_id: @ChannelId,
sequence: @Sequence
) -> ByteArray {
self.packet_acks.read(ack_key(port_id, channel_id, sequence))
}
}

#[generate_trait]
Expand All @@ -181,7 +196,9 @@ pub mod ChannelHandlerComponent {
channel_id: @ChannelId,
channel_end: ChannelEnd
) {
self.channel_ends.write(channel_end_key(port_id, channel_id), channel_end);
self
.channel_ends
.write(channel_end_key(port_id, channel_id), Option::Some(channel_end));
}

fn write_packet_receipt(
Expand All @@ -191,7 +208,19 @@ pub mod ChannelHandlerComponent {
sequence: @Sequence,
receipt: Receipt
) {
self.packet_receipts.write(receipt_key(port_id, channel_id, sequence), receipt);
self
.packet_receipts
.write(receipt_key(port_id, channel_id, sequence), Option::Some(receipt));
}

fn write_packet_ack(
ref self: ComponentState<TContractState>,
port_id: @PortId,
channel_id: @ChannelId,
sequence: @Sequence,
ack: ByteArray
) {
self.packet_acks.write(ack_key(port_id, channel_id, sequence), ack);
}
}

Expand Down
6 changes: 4 additions & 2 deletions cairo-contracts/packages/core/src/channel/errors.cairo
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
pub mod ChannelErrors {
pub const ACK_ALREADY_EXISTS: felt252 = 'ICS04: ack already exists';
pub const EMPTY_COMMITMENT_PROOF: felt252 = 'ICS04: empty commitment proof';
pub const INACTIVE_CLIENT: felt252 = 'ICS04: inactive client';
pub const INVALID_CHANNEL_STATE: felt252 = 'ICS04: invalid channel state';
pub const INVALID_COUNTERPARTY: felt252 = 'ICS04: invalid counterparty';
pub const TIMED_OUT_PACKET: felt252 = 'ICS04: packet timed out';
pub const INACTIVE_CLIENT: felt252 = 'ICS04: inactive client';
pub const INVALID_PROOF_HEIGHT: felt252 = 'ICS04: invalid proof height';
pub const MISSING_CHANNEL_END: felt252 = 'ICS04: missing channel end';
pub const TIMED_OUT_PACKET: felt252 = 'ICS04: packet timed out';
pub const UNSUPPORTED_PORT_ID: felt252 = 'ICS04: unsupported port id';
}
17 changes: 8 additions & 9 deletions cairo-contracts/packages/core/src/channel/types.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl PacketValidateBasicImpl of ValidateBasicTrait<Packet> {
fn validate_basic(self: @Packet) {}
}

#[derive(Clone, Debug, Drop, Serde, starknet::Store)]
#[derive(Clone, Debug, Drop, PartialEq, Serde, starknet::Store)]
pub struct ChannelEnd {
pub state: ChannelState,
pub ordering: ChannelOrdering,
Expand All @@ -58,9 +58,10 @@ pub impl ChannelEndImpl of ChannelEndTrait {

/// Returns true if the counterparty matches the given counterparty.
fn counterparty_matches(
self: @ChannelEnd, counterparty_port_id: @PortId, counterparty_chan_id: @ChannelId
self: @ChannelEnd, counterparty_port_id: @PortId, counterparty_channel_id: @ChannelId
) -> bool {
self.remote.port_id == counterparty_port_id && self.remote.chan_id == counterparty_chan_id
self.remote.port_id == counterparty_port_id
&& self.remote.channel_id == counterparty_channel_id
}
}

Expand All @@ -73,7 +74,7 @@ pub enum ChannelState {
Closed,
}

#[derive(Clone, Debug, Drop, Serde, starknet::Store)]
#[derive(Clone, Debug, Drop, PartialEq, Serde, starknet::Store)]
pub enum ChannelOrdering {
Unordered,
Ordered,
Expand All @@ -82,15 +83,13 @@ pub enum ChannelOrdering {
#[derive(Clone, Debug, Drop, PartialEq, Serde, starknet::Store)]
pub struct Counterparty {
pub port_id: PortId,
pub chan_id: ChannelId,
pub channel_id: ChannelId,
}

#[derive(Clone, Debug, Drop, Serde)]
pub struct Acknowledgement {
pub ack: felt252,
}

#[derive(Clone, Debug, Drop, Serde, starknet::Store)]
pub enum Receipt {
Ok
}
#[derive(Clone, Debug, Drop, PartialEq, Serde, starknet::Store)]
pub struct Receipt {}
4 changes: 2 additions & 2 deletions cairo-contracts/packages/core/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod router;

pub mod tests;
pub mod channel {
mod app_call;
mod components;
Expand All @@ -19,7 +19,7 @@ pub mod channel {
pub use msgs::{MsgRecvPacket, MsgRecvPacketImpl, MsgRecvPacketTrait};
pub use types::{
Packet, PacketImpl, PacketTrait, ChannelEnd, ChannelEndImpl, ChannelEndTrait, ChannelState,
ChannelOrdering, Counterparty, Acknowledgement, Receipt
ChannelOrdering, Counterparty, Acknowledgement, Receipt,
};
}
pub mod client {
Expand Down
6 changes: 6 additions & 0 deletions cairo-contracts/packages/core/src/tests.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod dummy;
pub(crate) mod mocks;

#[cfg(test)]
mod test_channel_handler;
pub(crate) use dummy::{CLIENT_ID, PORT_ID, CHANNEL_ID, SEQUENCE, CHANNEL_END};
27 changes: 27 additions & 0 deletions cairo-contracts/packages/core/src/tests/dummy.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use starknet_ibc_core::channel::{ChannelEnd, ChannelState, ChannelOrdering, Counterparty};
use starknet_ibc_core::host::{ClientId, PortId, ChannelId, Sequence};

pub fn CLIENT_ID() -> ClientId {
ClientId { client_type: '07-cometbft', sequence: 0 }
}

pub fn PORT_ID() -> PortId {
PortId { port_id: "transfer" }
}

pub fn CHANNEL_ID() -> ChannelId {
ChannelId { channel_id: "channel-0" }
}

pub fn SEQUENCE() -> Sequence {
Sequence { sequence: 1 }
}

pub fn CHANNEL_END() -> ChannelEnd {
ChannelEnd {
state: ChannelState::Open,
ordering: ChannelOrdering::Ordered,
remote: Counterparty { port_id: PORT_ID(), channel_id: CHANNEL_ID(), },
client_id: CLIENT_ID(),
}
}
1 change: 1 addition & 0 deletions cairo-contracts/packages/core/src/tests/mocks.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod channel_handler;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#[starknet::contract]
pub(crate) mod MockChannelHandler {
use starknet_ibc_core::channel::{ChannelHandlerComponent, ChannelEventEmitterComponent};

component!(
path: ChannelEventEmitterComponent,
storage: channel_emitter,
event: ChannelEventEmitterEvent
);
component!(path: ChannelHandlerComponent, storage: channel_handler, event: ChannelHandlerEvent);

impl ChannelInitializerImpl = ChannelHandlerComponent::ChannelInitializerImpl<ContractState>;

#[storage]
struct Storage {
#[substorage(v0)]
channel_emitter: ChannelEventEmitterComponent::Storage,
#[substorage(v0)]
channel_handler: ChannelHandlerComponent::Storage
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ChannelEventEmitterEvent: ChannelEventEmitterComponent::Event,
#[flat]
ChannelHandlerEvent: ChannelHandlerComponent::Event
}

#[constructor]
fn constructor(ref self: ContractState) {
self.channel_handler.initializer();
}
}
51 changes: 51 additions & 0 deletions cairo-contracts/packages/core/src/tests/test_channel_handler.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use ChannelHandlerComponent::ChannelReaderTrait;
use snforge_std::{spy_events, test_address, start_cheat_caller_address};
use starknet::ContractAddress;
use starknet::contract_address_const;
use starknet_ibc_core::channel::ChannelHandlerComponent::{
ChannelInitializerImpl, ChannelWriterTrait
};
use starknet_ibc_core::channel::ChannelHandlerComponent;
use starknet_ibc_core::tests::mocks::channel_handler::MockChannelHandler;
use starknet_ibc_core::tests::{CHANNEL_END, CHANNEL_ID, CLIENT_ID, PORT_ID, SEQUENCE};

type ComponentState = ChannelHandlerComponent::ComponentState<MockChannelHandler::ContractState>;

fn COMPONENT_STATE() -> ComponentState {
ChannelHandlerComponent::component_state_for_testing()
}

fn setup() -> ComponentState {
let mut state = COMPONENT_STATE();
state.initializer();
state
}

#[test]
fn test_read_empty_packet_receipt() {
let state = setup();
let receipt_res = state.read_packet_receipt(@PORT_ID(), @CHANNEL_ID(), @SEQUENCE());
assert!(receipt_res.is_none());
}

#[test]
fn test_read_empty_packet_ack() {
let state = setup();
let ack_res = state.read_packet_ack(@PORT_ID(), @CHANNEL_ID(), @SEQUENCE());
assert!(ack_res.len() == 0);
}

#[test]
#[should_panic]
fn test_read_empty_channel_end() {
let state = setup();
state.read_channel_end(@PORT_ID(), @CHANNEL_ID());
}

#[test]
fn test_channel_end_storage() {
let mut state = setup();
state.write_channel_end(@PORT_ID(), @CHANNEL_ID(), CHANNEL_END());
let chan_end_res = state.read_channel_end(@PORT_ID(), @CHANNEL_ID());
assert_eq!(chan_end_res, CHANNEL_END());
}

0 comments on commit a4f244a

Please sign in to comment.