update core IBC docs (#7560)

* update state

* add empty concept fields, update callbacks and messages

* update client creation, update and upgrade section

* add packet lifecycle concepts

* add host and proof section

* add connection handshake section

* add channel handshakes

* state transitions

* self review fixes

* Apply suggestions from code review

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* apply @fedekunze review suggestions

* packet data section

* Apply suggestions from code review

Co-authored-by: Christopher Goes <cwgoes@pluranimity.org>

* add @cwgoes and @fedekunze review suggestions

* fix typos

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Christopher Goes <cwgoes@pluranimity.org>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
colin axnér 2020-10-27 15:51:47 +01:00 committed by GitHub
parent 3d46c672f6
commit e306a852ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 395 additions and 62 deletions

View File

@ -381,7 +381,7 @@ func (k Keeper) ChanOpenConfirm(
//
// This section defines the set of functions required to close a channel handshake
// as defined in https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#closing-handshake
//
// ChanCloseInit is called by either module to close their end of the channel. Once
// closed, channels cannot be reopened.
func (k Keeper) ChanCloseInit(

View File

@ -59,6 +59,7 @@ type IBCModule interface {
) error
// OnRecvPacket must return the acknowledgement bytes
// In the case of an asynchronous acknowledgement, nil should be returned.
OnRecvPacket(
ctx sdk.Context,
packet channeltypes.Packet,

View File

@ -7,6 +7,71 @@ order: 1
> NOTE: if you are not familiar with the IBC terminology and concepts, please read
this [document](https://github.com/cosmos/ics/blob/master/ibc/1_IBC_TERMINOLOGY.md) as prerequisite reading.
## Client Creation, Updates, and Upgrades
IBC clients are on chain light clients. The light client is responsible for verifying
counterparty state. A light client can be created by any user submitting a client
identifier and a valid initial `ClientState` and `ConsensusState`. The client identifier
must not already be used. Clients are given a client identifier prefixed store to
store their associated client state and consensus states. Consensus states are
stored using their associated height.
Clients can be updated by any user submitting a valid `Header`. The client state callback
to `CheckHeaderAndUpdateState` is responsible for verifying the header against previously
stored state. The function should also return the updated client state and consensus state
if the header is considered a valid update. A light client, such as Tendermint, may have
client specific parameters like `TrustLevel` which must be considered valid in relation
to the `Header`. The update height is not necessarily the lastest height of the light
client. Updates may fill in missing consensus state heights.
Clients may be upgraded. The upgrade should be verified using `VerifyUpgrade`. It is not
a requirement to allow for light client upgrades. For example, the solo machine client
will simply return an error on `VerifyUpgrade`. Clients which implement upgrades
are expected to account for, but not necessarily support, planned and unplanned upgrades.
## Client Misbehaviour
IBC clients must freeze when the counterparty chain becomes byzantine and
takes actions that could fool the light client into accepting invalid state
transitions. Thus, relayers are able to submit Misbehaviour proofs that prove
that a counterparty chain has signed two Headers for the same height. This
constitutes misbehaviour as the IBC client could have accepted either header
as valid. Upon verifying the misbehaviour the IBC client must freeze at that
height so that any proof verifications for the frozen height or later fail.
Note, there is a difference between the chain-level Misbehaviour that IBC is
concerned with and the validator-level Evidence that Tendermint is concerned
with. Tendermint must be able to detect, submit, and punish any evidence of
individual validators breaking the Tendermint consensus protocol and attempting
to mount an attack. IBC clients must only act when an attack is successful
and the chain has successfully forked. In this case, valid Headers submitted
to the IBC client can no longer be trusted and the client must freeze.
Governance may then choose to override a frozen client and provide the correct,
canonical Header so that the client can continue operating after the Misbehaviour
submission.
## ClientUpdateProposal
A governance proposal may be passed to update a specified client with a provided
header. This is useful in unfreezing clients or updating expired clients. Each
client is expected to implement this functionality. A client may choose to disallow
an update by a governance proposal by returning an error in the client state function
'CheckProposedHeaderAndUpdateState'.
The localhost client cannot be updated by a governance proposal.
The solo machine client requires the boolean flag 'AllowUpdateAfterProposal' to be set
to true in order to be updated by a proposal. This is set upon client creation and cannot
be updated later.
The tendermint client has two flags update flags, 'AllowUpdateAfterExpiry' and
'AllowUpdateAfterMisbehaviour'. The former flag can only be used to unexpire clients. The
latter flag can be used to unfreeze a client and if necessary it will also unexpire the client.
It is advised to let a client expire if it has become frozen before proposing a new header.
This is to avoid the client from becoming refrozen if the misbehaviour evidence has not
expired. These boolean flags are set upon client creation and cannot be updated later.
## IBC Client Heights
IBC Client Heights are represented by the struct:
@ -61,27 +126,37 @@ Other client-types may implement their own logic to verify the IBC Heights that
The IBC interfaces expect an `ibcexported.Height` interface, however all clients should use the concrete implementation provided in
`02-client/types` and reproduced above.
## Client Misbehaviour
## Connection Handshake
IBC clients must freeze when the counterparty chain becomes malicious and
takes actions that could fool the light client into accepting invalid state
transitions. Thus, relayers are able to submit Misbehaviour proofs that prove
that a counterparty chain has signed two Headers for the same height. This
constitutes misbehaviour as the IBC client could have accepted either header
as valid. Upon verifying the misbehaviour the IBC client must freeze at that
height so that any proof verifications for the frozen height or later fail.
The connection handshake occurs in 4 steps as defined in [ICS 03](https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics).
Note, there is a difference between the chain-level Misbehaviour that IBC is
concerned with and the validator-level Evidence that Tendermint is concerned
with. Tendermint must be able to detect, submit, and punish any evidence of
individual validators breaking the Tendermint consensus protocol and attempting
to mount an attack. IBC clients must only act when an attack is successful
and the chain has successfully forked. In this case, valid Headers submitted
to the IBC client can no longer be trusted and the client must freeze.
`ConnOpenInit` is the first attempt to initialize a connection on the executing chain.
The handshake is expected to succeed if the connection identifier selected is not used and the
version selected is supported. The connection identifier for the counterparty connection may
be left empty indicating that the counterparty may select its own identifier. The connection
is set and stored in the INIT state upon success.
Governance may then choose to override a frozen client and provide the correct,
canonical Header so that the client can continue operating after the Misbehaviour
submission.
`ConnOpenTry` is a response to a chain executing `ConnOpenInit`. The executing chain will validate
the chain level parameters the counterparty has stored such as its chainID and consensus parameters.
The executing chain will also verify that if a previous connection exists for the specified
connection identifier that all the parameters match and its previous state was in INIT. This
may occur when both chains execute `ConnOpenInit` simultaneously. The executing chain will verify
that the counterparty created a connection in INIT state. The executing chain will also verify
The `ClientState` and `ConsensusState` the counterparty stores for the executing chain. The
executing chain will select a version from the intersection of its supported versions and the
versions set by the counterparty. The connection is set and stored in the TRYOPEN state upon
success.
`ConnOpenAck` may be called on a chain when the counterparty connection has entered TRYOPEN. A
previous connection on the executing chain must exist in either INIT or TRYOPEN. The executing
chain will verify the version the counterparty selected. If the counterparty selected its own
connection identifier, it will be validated in the basic validation of a `MsgConnOpenAck`.
The counterparty connection state is verified along with the `ClientState` and `ConsensusState`
stored for the executing chain. The connection is set and stored in the OPEN state upon success.
`ConnOpenConfirm` is a response to a chain executing `ConnOpenAck`. The executing chain's connection
must be in TRYOPEN. The counterparty connection state is verified to be in the OPEN state. The
connection is set and stored in the OPEN state upon success.
## Connection Version Negotiation
@ -124,6 +199,39 @@ with regards to version selection in `ConnOpenTry`. Each version in a set of
versions should have a unique version identifier.
:::
## Channel Handshake
The channel handshake occurs in 4 steps as defined in [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics).
`ChanOpenInit` is the first attempt to initialize a channel on top of an existing connection.
The handshake is expected to succeed if the channel identifier selected is not used and the
version selected for the existing connection is a supported IBC version. The portID must correspond
to a port already binded upon `InitChain`. The channel identifier for the counterparty channel
may be left empty indicating that the counterparty may select its own identifier. The channel is
set and stored in the INIT state upon success. The channel parameters `NextSequenceSend`,
`NextSequenceRecv`, and `NextSequenceAck` are all set to 1 and a channel capability is created
for the given portID and channelID path.
`ChanOpenTry` is a response to a chain executing `ChanOpenInit`. If the executing chain is calling
`ChanOpenTry` after previously executing `ChanOpenInit` then the provided channel parameters must
match the previously selected parameters. The connection the channel is created on top of must be
an OPEN state and its IBC version must support the desired channel type being created (ORDERED,
UNORDERED, etc). The executing chain will verify that the channel state of the counterparty is
in INIT. The executing chain will set and store the channel state in TRYOPEN. The channel
parameters `NextSequenceSend`, `NextSequenceRecv`, and `NextSequenceAck` are all set to 1 and
a channel capability is created for the given portID and channelID path only if the channel
did not previously exist.
`ChanOpenAck` may be called on a chain when the counterparty channel has entered TRYOPEN. A
previous channel on the executing chain must exist be in either INIT or TRYOPEN state. If the
counterparty selected its own channel identifier, it will be validated in the basic validation
of `MsgChanOpenAck`. The executing chain verifies that the counterparty channel state is in
TRYOPEN. The channel is set and stored in the OPEN state upon success.
`ChanOpenConfirm` is a response to a chain executing `ChanOpenAck`. The executing chain's
previous channel state must be in TRYOPEN. The executing chain verifies that the counterparty
channel state is OPEN. The channel is set and stored in the OPEN state upon success.
## Channel Version Negotiation
During the channel handshake procedure a version must be agreed upon between
@ -159,23 +267,119 @@ in the handshake callbacks.
Implementations which do not feel they would benefit from versioning can do
basic string matching using a single compatible version.
## ClientUpdateProposal
## Sending, Receiving, Acknowledging Packets
A governance proposal may be passed to update a specified client with a provided
header. This is useful in unfreezing clients or updating expired clients. Each
client is expected to implement this functionality. A client may choose to disallow
an update by a governance proposal by returning an error in the client state function
'CheckProposedHeaderAndUpdateState'.
Terminology:
**Packet Commitment** A hash of the packet stored on the sending chain.
**Packet Receipt** A single bit indicating that a packet has been received.
Used for timeouts.
**Acknowledgement** Data written to indicate the result of receiving a packet.
Typically conveying either success or failure of the receive.
The localhost client cannot be updated by a governance proposal.
A packet may be associated with one of the following states:
- the packet does not exist (ie it has not been sent)
- the packet has been sent but not received (the packet commitment exists on the
sending chain, but no receipt exists on the receiving chain)
- the packet has been received but not acknowledged (packet commitment exists
on the sending chain, a receipt exists on the receiving chain, but no acknowledgement
exists on the receiving chain)
- the packet has been acknowledgement but the acknowledgement has not been relayed
(the packet commitment exists on the sending chain, the receipt and acknowledgement
exist on the receiving chain)
- the packet has completed its life cycle (the packet commitment does not exist on
the sending chain, but a receipt and acknowledgement exist on the receiving chain)
The solo machine client requires the boolean flag 'AllowUpdateAfterProposal' to be set
to true in order to be updated by a proposal. This is set upon client creation and cannot
be updated later.
Sending of a packet is initiated by a call to the `ChannelKeeper.SendPacket`
function by an application module. Packets being sent will be verified for
correctness (core logic only). If the packet is valid, a hash of the packet
will be stored as a packet commitment using the packet sequence in the key.
Packet commitments are stored on the sending chain.
The tendermint client has two flags update flags, 'AllowUpdateAfterExpiry' and
'AllowUpdateAfterMisbehaviour'. The former flag can only be used to unexpire clients. The
latter flag can be used to unfreeze a client and if necessary it will also unexpire the client.
It is advised to let a client expire if it has become frozen before proposing a new header.
This is to avoid the client from becoming refrozen if the misbehaviour evidence has not
expired. These boolean flags are set upon client creation and cannot be updated later.
A message should be sent to the receving chain indicating that the packet
has been committed on the sending chain and should be received on the
receiving chain. The light client on the receiving chain, which verifies
the sending chain's state, should be updated to the lastest sending chain
state if possible. The verification will fail if the latest state of the
light client does not include the packet commitment. The receiving chain
is responsible for verifying that the counterparty set the hash of the
packet. If verification of the packet to be received is successful, the
receiving chain should store a receipt of the packet and call application
logic if necessary. An acknowledgement may be processed and stored at this time (synchronously)
or at another point in the future (asynchronously).
Acknowledgements written on the receiving chain may be verified on the
sending chain. If the sending chain successfully verifies the acknowledgement
then it may delete the packet commitment stored at that sequence. There is
no requirement for acknowledgements to be written. Only the hash of the
acknowledgement is stored on the chain. Application logic may be executed
in conjunction with verifying an acknowledgement. For example, in fungible
cross-chain token transfer, a failed acknowledgement results in locked or
burned funds being refunded.
Relayers are responsible for reconstructing packets between the sending,
receiving, and acknowledging of packets.
IBC applications sending and receiving packets are expected to appropriately
handle data contained within a packet. For example, cross-chain token
transfers will unmarshal the data into proto definitions representing
a token transfer.
Future optimizations may allow for storage cleanup. Stored packet
commitments could be removed from channels which do not write
packet acknowledgements and acknowledgements could be removed
when a packet has completed its life cycle.
## Timing out Packets
A packet may be timed out on the receiving chain if the packet timeout height or timestamp has
been surpassed on the receving chain or the channel has closed. A timed out
packet can only occur if the packet has never been received on the receiving
chain. ORDERED channels will verify that the packet sequence is greater than
the `NextSequenceRecv` on the receiving chain. UNORDERED channels will verify
that the packet receipt has not been written on the receiving chain. A timeout
on channel closure will additionally verify that the counterparty channel has
been closed. A successful timeout may execute application logic as appropriate.
Both the packet's timeout timestamp and the timeout height must have been
surpassed on the receiving chain for a timeout to be valid. A timeout timestamp
or timeout height with a 0 value indicates the timeout field may be ignored.
Each packet is required to have at least one valid timeout field.
## Closing Channels
Closing a channel occurs in occurs in 2 handshake steps as defined in [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics).
`ChanCloseInit` will close a channel on the executing chain if the channel exists, it is not
already closed and the connection it exists upon is OPEN. Channels can only be closed by a
calling module or in the case of a packet timeout on an ORDERED channel.
`ChanCloseConfirm` is a response to a counterparty channel executing `ChanCloseInit`. The channel
on the executing chain will be closed if the channel exists, the channel is not already closed,
the connection the channel exists upon is OPEN and the executing chain successfully verifies
that the counterparty channel has been closed.
## Port and Channel Capabilities
## Hostname Validation
Hostname validation is implemented as defined in [ICS 24](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements).
The 24-host sub-module parses and validates identifiers. It also builds
the key paths used to store IBC related information.
A valid identifier must conatin only alphanumeric characters or the
following list of allowed characters:
".", "\_", "+", "-", "#", "[", "]", "<", ">"
- Client identifiers must contain between 9 and 64 characters.
- Connection identifiers must contain between 10 and 64 characters.
- Channel identifiers must contain between 10 and 64 characters.
- Port identifiers must contain between 2 and 64 characters.
## Proofs
Proofs for counterparty state validation are provided as bytes. These bytes
can be unmarshaled into proto definitions as necessary by light clients.
For example, the Tendermint light client will use the bytes as a merkle
proof where as the solo machine client will unmarshal the proof into
several layers proto definitions used for signature verficiation.

View File

@ -4,18 +4,22 @@ order: 2
# State
The paths for the values stored in state can be found [here](https://github.com/cosmos/ics/blob/master/spec/ics-024-host-requirements/README.md#path-space). Additionally, the SDK adds
a prefix to the path to be able to aggregate the values for querying purposes.
The paths for the values stored in state is defined [here](https://github.com/cosmos/ics/blob/master/spec/ics-024-host-requirements/README.md#path-space).
Additionally, the SDK adds a prefix to the path to be able to aggregate the values for querying purposes.
The client type is not stored since it can be obtained through the client state.
| Prefix | Path | Value type |
|--------|------------------------------------------------------------------------|----------------|
| "0/" | "clients/{identifier}/clientState" | ClientState |
| "0/" | "clients/{identifier}/consensusStates/{height}" | ConsensusState |
| "0/" | "clients/{identifier}/type" | ClientType |
| "0/" | "connections/{identifier}" | ConnectionEnd |
| "0/" | "ports/{identifier}" | CapabilityKey |
| "0/" | "ports/{identifier}/channels/{identifier}" | ChannelEnd |
| "0/" | "ports/{identifier}/channels/{identifier}/key" | CapabilityKey |
| "0/" | "ports/{identifier}/channels/{identifier}/nextSequenceRecv" | uint64 |
| "0/" | "ports/{identifier}/channels/{identifier}/packets/{sequence}" | bytes |
| "0/" | "ports/{identifier}/channels/{identifier}/acknowledgements/{sequence}" | bytes |
| Prefix | Path | Value type |
|--------|-----------------------------------------------------------------------------|----------------|
| "0/" | "clients/{identifier}/clientState" | ClientState |
| "0/" | "clients/{identifier}/consensusStates/{height}" | ConsensusState |
| "0/" | "clients/{identifier}/connections" | []string |
| "0/" | "connections/{identifier}" | ConnectionEnd |
| "0/" | "ports/{identifier}" | CapabilityKey |
| "0/" | "channelEnds/ports/{identifier}/channels/{identifier}" | ChannelEnd |
| "0/" | "capabilities/ports/{identifier}/channels/{identifier}/key" | CapabilityKey |
| "0/" | "seqSends/ports/{identifier}/channels/{identifier}/nextSequenceSend" | uint64 |
| "0/" | "seqRecvs/ports/{identifier}/channels/{identifier}/nextSequenceRecv" | uint64 |
| "0/" | "seqAcks/ports/{identifier}/channels/{identifier}/nextSequenceAck" | uint64 |
| "0/" | "commitments/ports/{identifier}/channels/{identifier}/packets/{sequence}" | bytes |
| "0/" | "receipts/ports/{identifier}/channels/{identifier}/receipts/{sequence}" | bytes |
| "0/" | "acks/ports/{identifier}/channels/{identifier}/acknowledgements/{sequence}" | bytes |

View File

@ -4,3 +4,102 @@ order: 3
# State Transitions
The described state transitions assume successful message exection.
## Create Client
`MsgCreateClient` will initialize and store a `ClientState` and `ConsensusState` in the sub-store
created using the given client identifier.
## Update Client
`MsgUpdateClient` will update the `ClientState` and create a new `ConsensusState` for the
update height.
## Misbehaviour
`MsgSubmitMisbehaviour` will freeze a client.
## Upgrade Client
`MsgUpgradeClient` will upgrade the `ClientState` and `ConsensusState` to the update chain level
parameters and if applicable will update to the new light client implementation.
## Client Update Proposal
An Update Client Proposal will unfreeze a client and set an updated `ClientState` and a new
`ConsensusState`.
## Connection Open Init
`MsgConnectionOpenInit` will initialize a connection state in INIT.
## Connection Open Try
`MsgConnectionOpenTry` will initialize or update a connection state to be in TRYOPEN.
## Connection Open Ack
`MsgConnectionOpenAck` will update a connection state from INIT or TRYOPEN to be in OPEN.
## Connection Open Confirm
`MsgConnectionOpenAck` will update a connection state from TRYOPEN to OPEN.
## Channel Open Init
`MsgChannelOpenInit` will initialize a channel state in INIT. It will create a channel capability
and set all Send, Receive and Ack Sequences to 1 for the channel.
## Channel Open Try
`MsgChannelOpenTry` will initialize or update a channel state to be in TRYOPEN. If the channel
is being initialized, It will create a channel capability and set all Send, Receive and Ack
Sequences to 1 for the channel.
## Channel Open Ack
`MsgChannelOpenAck` will update the channel state to OPEN. It will set the version and channel
identifier for its counterparty.
## Channel Open Confirm
`MsgChannelOpenConfirm` will update the channel state to OPEN.
## Channel Close Init
`MsgChannelCloseInit` will update the channel state to CLOSED.
## Channel Close Confirm
`MsgChannelCloseConfirm` will update the channel state to CLOSED.
## Send Packet
A application calling `ChannelKeeper.SendPacket` will incremenet the next sequence send and set
a hash of the packet as the packet commitment.
## Receive Packet
`MsgRecvPacket` will increment the next sequence receive for ORDERED channels and set a packet
receipt for UNORDERED channels.
## Write Acknowledgement
`WriteAcknowledgement` may be executed synchronously during the execution of `MsgRecvPacket` or
asynchonously by an application module. It writes an acknowledgement to the store.
## Acknowledge Packet
`MsgAcknowledgePacket` deletes the packet commitment and for ORDERED channels increments next
sequences ack.
## Timeout Packet
`MsgTimeoutPacket` deletes the packet commitment and for ORDERED channels sets the channel state
to CLOSED.
## Timeout Packet on Channel Closure
`MsgTimeoutOnClose` deletes the packet commitment and for ORDERED channels sets the channel state
to CLOSED.

View File

@ -29,9 +29,8 @@ This message is expected to fail if:
- `Signer` is empty
- A light client with the provided id and type already exist
The message creates and stores a light client with the given ID and consensus type,
stores the validator set as the `Commiter` of the given consensus state and stores
both the consensus state and its commitment root (i.e app hash).
The message creates and stores a light client with an initial consensus state for the given client
identifier.
### MsgUpdateClient
@ -51,11 +50,36 @@ This message is expected to fail if:
- `Header` is empty or invalid
- `Signer` is empty
- A `ClientState` hasn't been created for the given ID
- the header's client type is different from the registered one
- the client is frozen due to misbehaviour and cannot be updated
- The client is frozen due to misbehaviour and cannot be updated
- The header fails to provide a valid update for the client
The message validates the header and updates the consensus state with the new
height, commitment root and validator sets, which are then stored.
The message validates the header and updates the client state and consensus state for the
header height.
### MsgUpgradeClient
```go
type MsgUpgradeClient struct {
ClientId string
ClientState *types.Any // proto-packed client state
UpgradeHeight *Height
ProofUpgrade []byte
Signer string
}
```
This message is expected to fail if:
- `ClientId` is invalid (not alphanumeric or not within 10-20 characters)
- `ClientState` is empty or invalid
- `UpgradeHeight` is empty or zero
- `ProofUpgrade` is empty
- `Signer` is empty
- A `ClientState` hasn't been created for the given ID
- The client is frozen due to misbehaviour and cannot be upgraded
- The upgrade proof fails
The message upgrades the client state and consensus state upon successful validation of a
chain upgrade.
### MsgSubmitMisbehaviour
@ -77,8 +101,7 @@ This message is expected to fail if:
- A `ClientState` hasn't been created for the given ID
- `Misbehaviour` check failed
The message validates the header and updates the consensus state with the new
height, commitment root and validator sets, which are then stored.
The message verifies the misbehaviour and freezes the client.
## ICS 03 - Connection
@ -432,7 +455,7 @@ This message is expected to fail if:
- `Packet` fails basic validation
- `Proof` does not prove that the packet has not been received on the counterparty chain.
The message times out a packet on chain B.
The message times out a packet that was sent on chain A and never received on chain B.
### MsgTimeoutOnClose
@ -461,7 +484,7 @@ This message is expected to fail if:
- `Proof` does not prove that the packet has not been received on the counterparty chain.
- `ProofClose` does not prove that the counterparty channel end has been closed.
The message times out a packet on chain B.
The message times out a packet that was sent on chain A and never received on chain B.
### MsgAcknowledgement
@ -486,4 +509,4 @@ This message is expected to fail if:
- `Acknowledgement` is empty
- `Proof` does not prove that the counterparty received the `Packet`.
The message receives a packet on chain A.
The message acknowledges that the packet sent from chainA was received on chain B.

View File

@ -4,7 +4,8 @@ order: 5
# Callbacks
Application modules implementing the IBC module must implement the following callbacks as found in [05-port](../core/05-port/types/module.go).
Application modules implementing the IBC module must implement the following callbacks as found in [05-port](../05-port/types/module.go).
More information on how to implement these callbacks can be found in the [implementation guide](../../../../docs/ibc/custom.md).
```go
// IBCModule defines an interface that implements all the callbacks
@ -59,6 +60,7 @@ type IBCModule interface {
) error
// OnRecvPacket must return the acknowledgement bytes
// In the case of an asynchronous acknowledgement, nil should be returned.
OnRecvPacket(
ctx sdk.Context,
packet channeltypes.Packet,