Synopsis
Learn how to implement theIBCModule
interface and all of the callbacks it requires.
The Cosmos SDK expects all IBC modules to implement the IBCModule
interface. This interface contains all of the callbacks IBC expects modules to implement. They include callbacks related to channel handshake, closing and packet callbacks (OnRecvPacket
, OnAcknowledgementPacket
and OnTimeoutPacket
).
module.go
file, add the following line:
Pre-requisite readings
Channel handshake callbacks
This section will describe the callbacks that are called during channel handshake execution. Among other things, it will claim channel capabilities passed on from core IBC. For a refresher on capabilities, check the Overview section. Here are the channel handshake callbacks that modules are expected to implement:Note that some of the code below is pseudo code, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. thecheckArguments
andnegotiateAppVersion
functions.
ChanCloseInit
and the finalizing chain calls ChanCloseConfirm
.
Channel handshake version negotiation
Application modules are expected to verify versioning used during the channel handshake procedure.OnChanOpenInit
will verify that the relayer-chosen parameters are valid and perform any customINIT
logic. It may return an error if the chosen parameters are invalid in which case the handshake is aborted. If the provided version string is non-empty,OnChanOpenInit
should return the version string if valid or an error if the provided version is invalid. If the version string is empty,OnChanOpenInit
is expected to return a default version string representing the version(s) it supports. If there is no default version string for the application, it should return an error if the provided version is an empty string.OnChanOpenTry
will verify the relayer-chosen parameters along with the counterparty-chosen version string and perform customTRY
logic. If the relayer-chosen parameters are invalid, the callback must return an error to abort the handshake. If the counterparty-chosen version is not compatible with this module’s supported versions, the callback must return an error to abort the handshake. If the versions are compatible, the try callback must select the final version string and return it to core IBC.OnChanOpenTry
may also perform custom initialization logic.OnChanOpenAck
will error if the counterparty selected version string is invalid and abort the handshake. It may also perform custom ACK logic.
Packet callbacks
Just as IBC expects modules to implement callbacks for channel handshakes, it also expects modules to implement callbacks for handling the packet flow through a channel, as defined in theIBCModule
interface.
Once a module A and module B are connected to each other, relayers can start relaying packets and acknowledgements back and forth on the channel.

- module A sends a packet through the IBC module
- the packet is received by module B
- if module B writes an acknowledgement of the packet then module A will process the acknowledgement
- if the packet is not successfully received before the timeout, then module A processes the packet’s timeout.
Sending packets
Modules do not send packets through callbacks, since the modules initiate the action of sending packets to the IBC module, as opposed to other parts of the packet flow where messages sent to the IBC module must trigger execution on the port-bound module through the use of callbacks. Thus, to send a packet a module simply needs to callSendPacket
on the IBCChannelKeeper
.
Note that some of the code below is pseudo code, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the EncodePacketData(customPacketData)
function.
In order to prevent modules from sending packets on channels they do not own,
IBC expects modules to pass in the correct channel capability for the packet’s
source channel.
Receiving packets
To handle receiving packets, the module must implement theOnRecvPacket
callback. This gets
invoked by the IBC module after the packet has been proved valid and correctly processed by the IBC
keepers. Thus, the OnRecvPacket
callback only needs to worry about making the appropriate state
changes given the packet data without worrying about whether the packet is valid or not.
Modules may return to the IBC handler an acknowledgement which implements the Acknowledgement
interface.
The IBC handler will then commit this acknowledgement of the packet so that a relayer may relay the
acknowledgement back to the sender module.
The state changes that occurred during this callback will only be written if:
- the acknowledgement was successful as indicated by the
Success()
function of the acknowledgement - if the acknowledgement returned is nil indicating that an asynchronous process is occurring
OnRecvPacket
callback will be written
for asynchronous acknowledgements.
Note that some of the code below is pseudo code, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the DecodePacketData(packet.Data)
function.
Acknowledgement
interface:
Acknowledging packets
After a module writes an acknowledgement, a relayer can relay back the acknowledgement to the sender module. The sender module can then process the acknowledgement using theOnAcknowledgementPacket
callback. The contents of the
acknowledgement is entirely up to the modules on the channel (just like the packet data); however, it
may often contain information on whether the packet was successfully processed along
with some additional data that could be useful for remediation if the packet processing failed.
Since the modules are responsible for agreeing on an encoding/decoding standard for packet data and
acknowledgements, IBC will pass in the acknowledgements as []byte
to this callback. The callback
is responsible for decoding the acknowledgement and processing it.
Note that some of the code below is pseudo code, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. theDecodeAcknowledgement(acknowledgments)
andprocessAck(ack)
functions.
Timeout packets
If the timeout for a packet is reached before the packet is successfully received or the counterparty channel end is closed before the packet is successfully received, then the receiving chain can no longer process it. Thus, the sending chain must process the timeout usingOnTimeoutPacket
to handle this situation. Again the IBC module will verify that the timeout is
indeed valid, so our module only needs to implement the state machine logic for what to do once a
timeout is reached and the packet can no longer be received.