Skip to content

Commit

Permalink
feat: add view functions for status of messages (#34)
Browse files Browse the repository at this point in the history
* feat: add view functions for status of messages

* Update src/messaging/tests/test_messaging.cairo

Co-authored-by: glihm <[email protected]>

* Update src/messaging/interface.cairo

Co-authored-by: glihm <[email protected]>

* Update src/messaging/interface.cairo

Co-authored-by: glihm <[email protected]>

* improve test

* Ran formatter

* Update returns to an enum

* update name

* updated the bindings

---------

Co-authored-by: glihm <[email protected]>
  • Loading branch information
byteZorvin and glihm authored Sep 5, 2024
1 parent ff8853f commit 517ea2b
Show file tree
Hide file tree
Showing 6 changed files with 1,090 additions and 803 deletions.
1,754 changes: 958 additions & 796 deletions bindings/src/bindings.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod messaging {
mod interface;
mod mock;
mod output_process;
mod types;

use component::messaging_cpt;
use interface::{IMessaging, IMessagingDispatcher, IMessagingDispatcherTrait};
Expand Down
25 changes: 22 additions & 3 deletions src/messaging/component.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ mod messaging_cpt {
};
use piltover::messaging::{
hash, interface::IMessaging, output_process::{MessageToStarknet, MessageToAppchain},
types::{MessageToAppchainStatus, MessageToStarknetStatus, MessageHash, Nonce}
};
use starknet::ContractAddress;
use super::errors;

type MessageHash = felt252;
type Nonce = felt252;

#[storage]
struct Storage {
/// Cancellation delay in seconds for message from Starknet to Appchain.
Expand Down Expand Up @@ -189,6 +187,27 @@ mod messaging_cpt {
(message_hash, nonce)
}

fn sn_to_appchain_messages(
self: @ComponentState<TContractState>, message_hash: MessageHash
) -> MessageToAppchainStatus {
let nonce = self.sn_to_appc_messages.read(message_hash);
if nonce == 0 {
return MessageToAppchainStatus::SealedOrNotSent;
}
return MessageToAppchainStatus::Pending(nonce);
}


fn appchain_to_sn_messages(
self: @ComponentState<TContractState>, message_hash: MessageHash
) -> MessageToStarknetStatus {
let message_count = self.appc_to_sn_messages.read(message_hash);
if (message_count == 0) {
return MessageToStarknetStatus::NothingToConsume;
}
return MessageToStarknetStatus::ReadyToConsume(message_count);
}

fn consume_message_from_appchain(
ref self: ComponentState<TContractState>,
from_address: ContractAddress,
Expand Down
36 changes: 32 additions & 4 deletions src/messaging/interface.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use piltover::messaging::types::{
MessageHash, Nonce, MessageToAppchainStatus, MessageToStarknetStatus
};
//! SPDX-License-Identifier: MIT
//!
//! Interface for Appchain - Starknet messaging.
Expand All @@ -20,7 +23,7 @@ trait IMessaging<T> {
/// The message hash and the updated nonce of the message.
fn send_message_to_appchain(
ref self: T, to_address: ContractAddress, selector: felt252, payload: Span<felt252>
) -> (felt252, felt252);
) -> (MessageHash, Nonce);

/// Consumes a message received from a state update of the Appchain.
///
Expand All @@ -36,7 +39,32 @@ trait IMessaging<T> {
/// Returns the hash of the consummed message.
fn consume_message_from_appchain(
ref self: T, from_address: ContractAddress, payload: Span<felt252>
) -> felt252;
) -> MessageHash;

/// Checks the status of message sent to the Appchain from Starknet
/// <https://github.com/starkware-libs/cairo-lang/blob/caba294d82eeeccc3d86a158adb8ba209bf2d8fc/src/starkware/starknet/solidity/StarknetMessaging.sol#L39>
///
/// # Arguments
///
/// * `message_hash` - The hash of the message that was sent to the Appchain.
///
/// # Returns
///
/// Returns the Nonce used for the message with the given `msgHash`,
/// or 0 if no message with such a hash is pending.
fn sn_to_appchain_messages(self: @T, message_hash: felt252) -> MessageToAppchainStatus;

/// Checks the status of message sent to the Starknet from the Appchain
/// <https://github.com/starkware-libs/cairo-lang/blob/caba294d82eeeccc3d86a158adb8ba209bf2d8fc/src/starkware/starknet/solidity/StarknetMessaging.sol#L43>
///
/// # Arguments
///
/// * `message_hash` - The hash of the message that was sent to Starknet.
///
/// # Returns
///
/// Returns the count of messages with given `msg_hash` that are pending to be consumed on starknet, otherwise 0
fn appchain_to_sn_messages(self: @T, message_hash: felt252) -> MessageToStarknetStatus;

/// Starts the cancellation procedure for a message sent from
/// Starknet to the Appchain.
Expand All @@ -61,7 +89,7 @@ trait IMessaging<T> {
selector: felt252,
payload: Span<felt252>,
nonce: felt252,
) -> felt252;
) -> MessageHash;

/// Cancels a message from Starknet to Appchain if the cancellation delays has expired.
///
Expand All @@ -83,5 +111,5 @@ trait IMessaging<T> {
selector: felt252,
payload: Span<felt252>,
nonce: felt252,
) -> felt252;
) -> MessageHash;
}
63 changes: 63 additions & 0 deletions src/messaging/tests/test_messaging.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::array::ArrayTrait;
use core::zeroable::Zeroable;
use openzeppelin::tests::utils::constants as c;
use piltover::messaging::{
Expand All @@ -7,6 +8,7 @@ use piltover::messaging::{
Event, MessageSent, MessageCancellationStarted, MessageCanceled, MessageToStarknetReceived,
MessageToAppchainSealed,
},
types::{MessageHash, MessageToAppchainStatus, MessageToStarknetStatus},
output_process::{MessageToStarknet, MessageToAppchain}, hash, output_process,
};
use snforge_std as snf;
Expand Down Expand Up @@ -177,6 +179,44 @@ fn send_message_ok() {
spy.assert_emitted(@array![(mock.contract_address, Event::MessageSent(expected_event))]);
}

#[test]
fn sn_to_appchain_messages_ok() {
let (mock, mut spy) = deploy_mock();

let from = c::SPENDER();
let to = c::RECIPIENT();
let selector = selector!("func1");
let payload = array![1, 2, 3];

snf::start_prank(CheatTarget::One(mock.contract_address), from);

// Calculate the message_hash
let message_hash = hash::compute_message_hash_sn_to_appc(
nonce: 1, to_address: to, :selector, payload: payload.span()
);
let is_pending_before = mock.sn_to_appchain_messages(message_hash);
assert(
is_pending_before == MessageToAppchainStatus::SealedOrNotSent,
'Should not be pending before'
);

snf::start_prank(CheatTarget::One(from), from);
let (message_hash, nonce) = mock.send_message_to_appchain(to, selector, payload.span());

// Ensure the message is pending to consume
let is_pending_after = mock.sn_to_appchain_messages(message_hash);
assert(
is_pending_after == MessageToAppchainStatus::Pending(nonce),
'message not registered/pending'
);

let expected_event = MessageSent {
message_hash, from, to, selector, nonce: nonce, payload: payload.span(),
};

spy.assert_emitted(@array![(mock.contract_address, Event::MessageSent(expected_event))]);
}

#[test]
fn start_cancellation_ok() {
let (mock, mut spy) = deploy_mock();
Expand Down Expand Up @@ -414,6 +454,29 @@ fn consume_message_from_appchain_ok() {
mock.consume_message_from_appchain(from, payload);
}

#[test]
fn appchain_to_sn_messages_ok() {
let mut mock = mock_state_testing();

let from = c::SPENDER();
let to = starknet::get_contract_address();
let payload = array![1, 2, 3].span();

let messages = array![MessageToStarknet { from_address: from, to_address: to, payload, }]
.span();

let message_hash = hash::compute_message_hash_appc_to_sn(from, to, payload);

let previous_status = mock.appchain_to_sn_messages(message_hash);
assert(previous_status == MessageToStarknetStatus::NothingToConsume, 'message already present');

mock.process_messages_to_starknet(messages);

// Ensure that message is available to consume
let count_after = mock.appchain_to_sn_messages(message_hash);
assert(count_after == MessageToStarknetStatus::ReadyToConsume(1), 'message not be present');
}

#[test]
#[should_panic(expected: ('INVALID_MESSAGE_TO_CONSUME',))]
fn consume_message_from_appchain_invalid_to_consume() {
Expand Down
14 changes: 14 additions & 0 deletions src/messaging/types.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub type MessageHash = felt252;
pub type Nonce = felt252;

#[derive(Serde, Drop, Eq, PartialEq)]
pub enum MessageToAppchainStatus {
SealedOrNotSent, // sn->appc: The nonce is 0 for the message hash.
Pending: Nonce, // sn->appc: The nonce > 0.
}

#[derive(Serde, Drop, Eq, PartialEq)]
pub enum MessageToStarknetStatus {
NothingToConsume, // appc->sn: the ref count is 0.
ReadyToConsume: felt252 // appc->sn: the ref count > 0.
}

0 comments on commit 517ea2b

Please sign in to comment.