-
Notifications
You must be signed in to change notification settings - Fork 28
IBC Notes
When an IBC Transfer is triggered, it is just the beginning.
A user signed a transaction containing a MsgTransfer
message, and broadcast it to the network.
Later, when the transaction succeeds and is written into a block, the network will generate related events. These events will be caught by Relayers, and they will sign other corresponding transactions to do the communication between two networks.
A full IBC Transfer lifecycle could be:
Success case:
-
MsgTransfer
msg detected on Chain A:- A user signs a transaction on Chain A, and the transaction is executed and is written to a block.
-
MsgRecvPacket
msg detected on Chain B:- Relayer signs a transaction containing
MsgRecvPacket
msg on Chain B. It tells Chain B that one IBC Transfer has triggered on Chain A. - The IBC Transfer packet is received and handled on Chain B.
- The IBC Transfer could be either succeed or fail.
- Relayer signs a transaction containing
-
MsgAcknowledgement
msg detected on Chain A:- Relayer signs a transaction containing
MsgAcknowledgement
msg on Chain A. It tells Chain A that the IBC Transfer is handled on Chain B. - The IBC Transfer could be either succeed or fail.
- The IBC Transfer is finished.
- Relayer signs a transaction containing
Failure case:
-
MsgTransfer
msg detected on Chain A:- A user signs a transaction on Chain A, and the transaction is executed and is written to a block.
-
MsgTimeout
msg detected on Chain A:- Relayer signs a transaction containing
MsgTimeout
msg on Chain A. It tells Chain A that the IBC Transfer timeouts.
- Relayer signs a transaction containing
One problem is that for each IBC Channel, there could be multiple relayers monitoring it. Therefore, there is a race condition between relayers. Each IBC Transfer could be relayed by multiple relayers.
For example, when one tx containing MsgTransfer
is on Chain A, you might see multiple corresponding txs containing MsgRecvPacket
on Chain B.
Although there will be multiple MsgRecvPacket
msg for one MsgTransfer
, only one of the MsgRecvPacket
will be executed. Others will be ignored by CosmosSDK, they will do no-operation
to the duplicate relayed msgs.
Similar behavior also exists on MsgAcknowledgement
and MsgTimeout
.
Code references on CosmosSDK:
- https://github.com/cosmos/ibc-go/blob/760d15a3a55397678abe311b7f65203b2e8437d6/modules/core/04-channel/keeper/packet.go#L239
- https://github.com/cosmos/ibc-go/blob/760d15a3a55397678abe311b7f65203b2e8437d6/modules/core/keeper/msg_server.go#L508
From an indexing perspective, we are not interested in those multiple relayed msgs, and we want to ignore them.
In order to do that, we introduced a set of customized Msgs, which is defined by ourselves:
MsgAlreadyRelayedIBCRecvPacket
MsgAlreadyRelayedIBCAcknowledgement
MsgAlreadyRelayedIBCTimeout
MsgAlreadyRelayedIBCTimeoutOnClose
During the parsing of block
and block_results
, when those multiple relayed msgs are detected, they will be converted to the above-mentioned customized Msgs.
Our existing projections will not handle these messages, which fulfills the target of ignoring them.
For MsgRecvPacket
:
- If success:
-
msgIBCRecvPacket.Params.MaybeFungibleTokenPacketData.Success
should betrue
. -
msgIBCRecvPacket.Params.PacketAck.MaybeError
should benil
.
-
- If failure:
-
msgIBCRecvPacket.Params.MaybeFungibleTokenPacketData.Success
should befalse
. -
msgIBCRecvPacket.Params.PacketAck.MaybeError
should contain error message.
-
For MsgAcknowledgement
:
- If success:
-
msgIBCAcknowledgement.Params.MaybeFungibleTokenPacketData.Success
should betrue
. -
msgIBCAcknowledgement.Params.MaybeFungibleTokenPacketData.MaybeError
should benil
.
-
- If failure:
-
msgIBCAcknowledgement.Params.MaybeFungibleTokenPacketData.Success
should befalse
. -
msgIBCAcknowledgement.Params.MaybeFungibleTokenPacketData.MaybeError
should contain error message.
-
A good reference from Cosmos: https://tutorials.cosmos.network/understanding-ibc-denoms/
An IBC Denom has two formats:
-
[<port-id>/<channel-id>/]<original-denom>
:- e.g.
transfer/channel-0/basecro
,basecro
- e.g.
-
ibc/XXXX
: (ibc/
followed by a sha256 hash)- e.g.
ibc/6411AE2ADA1E73DB59DB151A8988F9B7D5E7E233D8414DB6817F8F1A01611F86
- e.g.
The two formats are representing the same thing:
ibc/
+ sha256("transfer/channel-0/basecro")
= ibc/6411AE2ADA1E73DB59DB151A8988F9B7D5E7E233D8414DB6817F8F1A01611F86
One problem caused by the formats is in tx raw MsgTransfer
messages, its token denom could be in [<port-id>/<channel-id>/]<original-denom>
format or ibc/XXXX
format.
As we need to calculate the bonded_tokens
for each IBC Channel, we want to always represent denom in [<port-id>/<channel-id>/]<original-denom>
format in our system.
To keep the denom consistent when doing related calculation, for MsgTransfer
message:
- Always use:
msgIBCTransferTransfer.Params.PacketData.Denom
, as it is always in[<port-id>/<channel-id>/]<original-denom>
format. - Not recommend to use:
msgIBCTransferTransfer.Params.Token.Denom
, as it is possible inibc/XXXX
format.