# Adding Packet and Acknowledgement Data
This section demonstrates how to define packets and acks (acknowledgements) for the leaderboard blockchain.
This blockchain will mostly be receiving packets from the checkers blockchain or other gaming chains, not sending them. This will be handled in the checkers blockchain extension section.
In this section, you will add an additional packet definition that will enable the Leaderboard chain to send a packet to connected game chains when a player has entered the top of the rankings. It is up to you if you want to include this in the Leaderboard chain you will build in the checkers extension exercise.
The documentation on how to define packets and acks in the Inter-Blockchain Communication Protocol (IBC) can be found in the ibc-go docs (opens new window).
# Scaffold a packet with Ignite CLI
You are now going to scaffold the IBC packet data with Ignite CLI, and compare it once more with git diff:
The packet is called
ibcTopRank, which includes the fields
score. Additionally, you send back the
playerId of the player who entered the top of the rankings through the
The output on the terminal gives an overview of the changes made:
In the next paragraphs, you will investigate each of the most important additions to the code.
# Proto definitions
The first additions are to the proto definitions in the
One addition is
The next addition is the ack:
tx.proto a Message service is added:
The proto message
MsgSendIbcTopRank includes the field
timeoutTimestamp, which is added by Ignite CLI when scaffolding an IBC packet. This is an IBC channel parameter that is important in IBC and Ignite CLI abstracts this away, removing the need for the user to add this manually.
The proto definitions will be compiled into
# CLI commands
Ignite CLI also creates CLI commands to send packets and adds them to the
Packets can be sent from the CLI with the following command:
SendPacket and packet callback logic
When scaffolding an IBC module with Ignite CLI, you already saw the implementation of the
IBCModule interface, including a bare-bones packet callbacks structure. Now that you have also scaffolded a packet (and ack), the callbacks have been added with logic to handle the receive, ack, and timeout scenarios.
Additionally, for the sending of a packet, a message server has been added that handles a SendPacket message, in this case
IBC allows some freedom to the developers regarding how to implement the custom logic, decoding and encoding packets, and processing acks. The provided structure is but one example of how to tackle this. Therefore, it makes sense to focus on the general flow to handle user messages or IBC callbacks rather than the specific implementation by Ignite CLI.
# Sending packets
To handle a user submitting a message to send an IBC packet, a message server is added to the handler:
It calls the
SendIbcTopRank method on the message server, defined as:
This in turn calls the
TransmitIbcTopRankPacket method on the module's keeper, defined in
x/leaderboard/keeper/ibc_top_rank.go. This method gets all of the required metadata from core IBC before sending the packet using the ChannelKeeper's
When you want to add additional custom logic before transmitting the packet, you do this in the
SendIbcTopRank method on the message server.
# Receiving packets
In a previous section you examined the
OnRecvPacket callback in the
x/leaderboard/module_ibc.go file. There, Ignite CLI had set up a structure to dispatch the packet depending on packet type through a switch statement. Now by adding the
IbcTopRank packet, a case has been added:
The first line of code in the case statement calls the application's
OnRecvIbcTopRankPacket callback on the keeper to process the reception of the packet:
Remember that the
OnRecvPacket callback writes an acknowledgement as well (this course covers the synchronous write ack case).
# Acknowledging packets
Similarly to the
OnRecvPacket case before, Ignite CLI has already prepared the structure of the
OnAcknowledgementPacket with the switch statement. Again, scaffolding the packet adds a case to the switch:
This calls into the newly created application keeper's ack packet callback:
This allows us to add custom application logic for both failed and successful acks.
# Timing out packets
Timing out the packets follows the same flow, adding a case to the switch statement in
OnTimeoutPacket, calling into the keeper's timeout packet callback where the custom logic can be implemented. It is left to the reader to investigate this independently.
# Extra details
Next to the above, some additions have also been made to the
types package. These include
codec.go (opens new window),
events_ibc.go (opens new window), and
messages_ibc_top_rank.go (opens new window).
Again, the reader is invited to check these out independently.
Events in IBC are important because relayers process events to check if there are packets (or acknowledgements) to relay.
Ignite CLI has scaffolded some events in
x/leaderboard/types/events_ibc.go for timeout and the
ibcTopRank packet which you have defined:
Here are found both the
Event type and the attributes it contains.
These are not the only relevant events for IBC, though, the others can be found in the core IBC source code:
- Client events (opens new window)
- Connection events (opens new window)
- Channel events (opens new window)
You can go back to the code examined so far to take note of the events emitted.
To summarize, this section has explored:
- Scaffolding a chain with an IBC-enabled module, with both chain and module called leaderboard.
- How Ignite CLI made sure to implement the
IBCModuleinterface, including channel handshake and packet callbacks.
- How Ignite CLI has bound our IBC module to a port and added a route to the IBC router.
- Scaffolding an IBC packet,
- How Ignite CLI defined the packet and ack data.
- How Ignite CLI sets up the basic message handling and packet handling to send, receive, acknowledge, and timeout packets.
Even though the ability to send and receive packets is now enabled, no application logic to execute has yet been implemented. This is outside the scope of this section. The reader is invited to follow the checkers blockchain extension exercise.
When scaffolding a packet, Ignite CLI will ensure the chain can act both as the sender or receiver of a packet by default. This is a symmetrical setup which makes sense for some applications, like ICS20.
However, it is also possible to have an asymmetrical setup where one chain will always be the source or destination chain for a given packet, not both. In this case, the message server and packet callbacks can be updated to error when, for example, a chain receives a packet though it is supposed to exclusively be the destination chain. Interchain accounts or ICS27 is an example of this asymmetrical situation, as is the checkers extension exercise.