Skip to main content

Integrate Inter-Chain Messaging Facility (ICMF)

This documentation is for dapp developers looking to integrate the Interchain Messaging Facility (ICMF) into their decentralized applications. ICMF facilitates cross-chain communication, enabling interaction between blockchains within a dapp cluster. This guide will walk you through sending and receiving ICMF messages in your dapps.

ICMF operates as an event-based service. When blockchain_#1 emits events through transactions that contain event data written to block headers, blockchain_#2 subscribes to specific topics to read this data. Other blockchains (blockchain_n) can also subscribe to events from blockchain_#1. As soon as blockchain_#2 reads an event, it triggers the corresponding function. This enables multiple communication channels between blockchains in a dapp cluster.

From a development standpoint, ICMF supports both omnidirectional and multidirectional communication. In omnidirectional scenarios, blockchain_#1 emits events that blockchain_#2 and blockchain_#n can read. In multidirectional channels, all blockchains subscribe to topics and listen to each other, emitting events that trigger function calls.

Implementation

For simplification purposes, we will refer to the blockchain that sends event messages as sender_chain, while the blockchain that reads those events will be referred to as receiver_chain. In this context, dapps are responsible for processing the business logic that either sends a transaction with the event data or handles the received data. The dapp that sends the message is termed sender_dapp, and the dapp that handles the message is called receiver_dapp.

Refer to the infographics below to see how ICMF operates:

cross chain transfer structure
  1. The sender_dapp submits a transaction with the event data by calling the send_message function from the ICMF Rell library.
  2. The network validates the transaction on the sender_chain, and the message gets written to the block header.
  3. The receiver_chain checks for messages on subscribed topics in the block headers of the sender_chain.
  4. When the system detects a message, the dapp automatically invokes the __icmf_message operation. This function includes the necessary logic to handle the message.
  5. The ICMF Rell library calls the function handle_icmf_message, executing any logic defined by the dapp.

Send messages

Integration steps

To enable your blockchain to send ICMF messages, you need to add the ICMF Sender GTX module to your blockchain configuration.

  1. Open your blockchain's configuration file.

  2. Under the config section, insert the gtx module:

    config:
    gtx:
    modules:
    - "net.postchain.d1.icmf.IcmfSenderGTXModule"
  3. If your chain sends large messages, adjust the message query limit to avoid an overload of large queries:

    config:
    icmf:
    sender:
    message_query_limit: 100 # Default is 100, adjust to manage processing of large message queries
  4. Save and apply the configuration changes.

Send ICMF messages

After you integrate the ICMF Sender GTX module, you can use the ICMF module to send messages. Use the function send_message(topic: text, body: gtv) for this purpose. The topic parameter represents the message topic, while the body parameter contains the content of the message. To install the ICMF rell code library, see the instructions here.

Remember that the body parameter is of type gtv, which allows you to send messages with various data structures. Ensure that the receivers can parse the data you send. If you want to learn more about how to serialize and deserialize data when sending and receiving messages, refer to the GTV protocol description.

Receive messages

Integration steps

To enable your blockchain to receive ICMF messages, follow these steps to add the ICMF Receiver GTX module and the ICMF Receiver Synchronization Infrastructure Extension to your blockchain configuration.

  1. Open your blockchain's configuration file.

  2. Locate the gtx section under config and insert the following lines:

    gtx:
      modules:
    - "net.postchain.d1.icmf.IcmfReceiverGTXModule"

    sync_ext:
    - "net.postchain.d1.icmf.IcmfReceiverSynchronizationInfrastructureExtension"
  3. Save and apply the configuration changes.

Implement message reception

To process the received ICMF messages, you need to implement the message receive operation in Rell. Here's an example implementation:

operation __icmf_message(sender: byte_array, topic: text, body: gtv) {
// Parse and handle the message here
}
ArgumentDescription
senderRepresents the blockchain-rid of the sender chain.
topicSpecifies the message topic.
bodyThis argument carries the message content.

If you want to utilize the ICMF Rell library for receiving messages, extend the function like this:

@extend(receive_icmf_message) function handle_icmf_message(sender: byte_array, topic: text, body: gtv) {
}

Configure topics and sender chains

ICMF messages organize around topics that serve as communication channels, directing messages to their intended recipients. When you work with ICMF topics, follow these guidelines:

  • Prefix all ICMF topics with L_. This prefix indicates that the message is sent within your local blockchain network.
  • Only system chains can send messages on a global level.

To specify which topics and sender chains your blockchain listens to, configure the ICMF receiver settings in your blockchain's configuration file:

icmf:
  receiver:
    local:
- bc-rid: x"0000000000000000000000000000000000000000000000000000000000000001"
        topic: "L_topic1"
- bc-rid: x"0000000000000000000000000000000000000000000000000000000000000002"
        topic: "L_topic2"
skip-to-height: 10 # Skip messages from this topic until block height 10
- etc.

In the icmf section, under receiver, list the chains and topics your blockchain should monitor. The bc-rid parameter refers to the blockchain-rid of the sender chain, and the topic parameter specifies the topic of interest.

The skip-to-height parameter ensures that messages on the specified topic will be skipped until the mentioned block height.

Combining ICMF with other extensions

ICMF usually tries to accommodate as many messages as possible into a block. However, when used alongside other extensions, you might need to adjust the space ICMF allocates for them. Use the following configuration to ensure better coordination with other extensions:

config:
icmf:
receiver:
special-tx-margin-bytes: 102400 # Default is 100 KiB; adjust if other extensions require more space

This configuration allows for improved coordination with other extensions by ensuring that ICMF does not consume excessive space in the block.

Staking updates

The ICMF allows your blockchain to configure the global staking topic G_staking_state_update which will allow any chain to listen to the staking messages. The messages include the following information:

  • The unique account identifier.
  • Total staked amount including any active withdrawals.
  • A list of active withdrawal requests.

Each message will provide an update for a specific account. Any changes related to staking, such as new staking or withdrawals, will trigger the publication of a new message on the relevant topic for that account. This message will include the most current value of the amount staked.

For demonstration purposes, refer to the code example below which highlights the configuration of the staking topic:

module;

import lib.icmf.constants.*;

/** Topic for staking state updates related to account balance and withdrawals */
val economy_chain_staking_state_update = ICMF_TOPIC_GLOBAL_PREFIX + "staking_state_update";

struct economy_chain_staking_state_withdrawal {
/** Requested amount to withdraw in minor units */
amount: integer;

/** Approximate time when this withdraw is scheduled */
finish_at: integer;
}

/**
* Keeps the staking balance and active withdrawals for a specific FT4 account id.
*/
struct economy_chain_staking_state_update_message {

/** Staking FT4 account id */
staking_account_id: pubkey;

/** Total staked amount in minor units including any active withdrawal */
balance: integer;

/** List of active withdrawal requests */
withdrawals: list<economy_chain_staking_state_withdrawal>;
}
tip

For an in-depth course on using ICMF in a real dapp, visit the Build an event-driven multi-blockchain dapp course.