Update IBC Application Guide (#8256)

* fix app doc

* finish updating guide

* Update docs/ibc/overview.md

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* apply @colin-axner suggestions

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
Aditya 2021-01-05 23:01:13 +00:00 committed by GitHub
parent 893f2262a7
commit 031eec3e9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 9 deletions

View File

@ -49,7 +49,9 @@ func (k Keeper) OnChanOpenInit(ctx sdk.Context,
version string,
) error {
// OpenInit must claim the channelCapability that IBC passes into the callback
k.scopedKeeper.ClaimCapability(ctx, channelCap)
if err := k.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil {
return err
}
// ... do custom initialization logic
@ -72,9 +74,17 @@ OnChanOpenTry(
version,
counterpartyVersion string,
) error {
// OpenInit must claim the channelCapability that IBC passes into the callback
k.scopedKeeper.ClaimCapability(ctx, channelCap)
// Module may have already claimed capability in OnChanOpenInit in the case of crossing hellos
// (ie chainA and chainB both call ChanOpenInit before one of them calls ChanOpenTry)
// If the module can already authenticate the capability then the module already owns it so we don't need to claim
// Otherwise, module does not have channel capability and we must claim it from IBC
if !k.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) {
// Only claim channel capability passed back by IBC module if we do not already own it
if err := k.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil {
return err
}
}
// ... do custom initialization logic
// Use above arguments to determine if we want to abort handshake
@ -285,7 +295,7 @@ invoked by the IBC module after the packet has been proved valid and correctly p
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 must return an acknowledgement as a byte string and return it to the IBC handler.
Modules may return an acknowledgement as a byte string and return it to the IBC handler.
The IBC handler will then commit this acknowledgement of the packet so that a relayer may relay the
acknowledgement back to the sender module.
@ -331,8 +341,14 @@ acknowledgement. An example of this technique is in the `ibc-transfer` module's
### Acknowledgements
Modules must commit an acknowledgement upon receiving and processing a packet. This
acknowledgement can then be relayed back to the original sender chain, which can take action
Modules may commit an acknowledgement upon receiving and processing a packet in the case of synchronous packet processing.
In the case where a packet is processed at some later point after the packet has been received (asynchronous execution), the acknowledgement
will be written once the packet has been processed by the application which may be well after the packet receipt.
NOTE: Most blockchain modules will want to use the synchronous execution model in which the module processes and writes the acknowledgement
for a packet as soon as it has been received from the IBC module.
This acknowledgement can then be relayed back to the original sender chain, which can take action
depending on the contents of the acknowledgement.
Just as packet data was opaque to IBC, acknowledgements are similarly opaque. Modules must pass and
@ -344,12 +360,31 @@ example above. [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-c
specifies a recommended format for acknowledgements. This acknowledgement type can be imported from
[channel types](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel/types).
While modules may choose arbitrary acknowledgement structs, a default acknowledgement types is provided by IBC [here](https://github.com/cosmos/cosmos-sdk/blob/master/proto/ibc/core/channel/v1/channel.proto):
```proto
// Acknowledgement is the recommended acknowledgement format to be used by
// app-specific protocols.
// NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental
// conflicts with other protobuf message formats used for acknowledgements.
// The first byte of any message with this format will be the non-ASCII values
// `0xaa` (result) or `0xb2` (error). Implemented as defined by ICS:
// https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope
message Acknowledgement {
// response contains either a result or an error and must be non-empty
oneof response {
bytes result = 21;
string error = 22;
}
}
```
#### Acknowledging Packets
After a module writes an acknowledgement while receiving a packet. a relayer can relay back the acknowledgement to the sender module. The sender module can
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 the `OnAcknowledgementPacket` callback. The contents of the
acknowledgement is entirely upto the modules on the channel (just like the packet data); however, it
may often contain information on whether the packet was successfully received and processed along
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

View File

@ -141,6 +141,34 @@ Thus, packet data is completely opaque to IBC handlers. It is incumbent on a sen
their application-specific packet information into the `Data` field of packets, and the receiver
module to decode that `Data` back to the original application data.
### [Receipts and Timeouts](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel)
Since IBC works over a distributed network and relies on potentially faulty relayers to relay messages between ledgers,
IBC must handle the case where a packet does not get sent to its destination in a timely manner or at all. Thus, packets must
specify a timeout height or timeout timestamp after which a packet can no longer be successfully received on the destination chain.
If the timeout does get reached, then a proof of packet timeout can be submitted to the original chain which can then perform
application-specific logic to timeout the packet, perhaps by rolling back the packet send changes (refunding senders any locked funds, etc).
In ORDERED channels, a timeout of a single packet in the channel will cause the channel to close. If packet sequence `n` times out,
then no packet at sequence `k > n` can be successfully received without violating the contract of ORDERED channels that packets are processed in the order that they are sent. Since ORDERED channels enforce this invariant, a proof that sequence `n` hasn't been received on the destination chain by packet `n`'s specified timeout is sufficient to timeout packet `n` and close the channel.
In the UNORDERED case, packets may be received in any order. Thus, IBC will write a packet receipt for each sequence it has received in the UNORDERED channel. This receipt contains no information, it is simply a marker intended to signify that the UNORDERED channel has received a packet at the specified sequence. To timeout a packet on an UNORDERED channel, one must provide a proof that a packet receipt does not exist for the packet's sequence by the specified timeout. Of course, timing out a packet on an UNORDERED channel will simply trigger the application specific timeout logic for that packet, and will not close the channel.
For this reason, most modules should use UNORDERED channels as they require less liveness guarantees to function effectively for users of that channel.
### [Acknowledgements](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel)
Modules may also choose to write application-specific acknowledgements upon processing a packet. This may either be done synchronously on `OnRecvPacket`, if the module processes packets as soon as they are received from IBC module. Or they may be done asynchronously if module processes packets at some later point after receiving the packet.
Regardless, this acknowledgement data is opaque to IBC much like the packet `Data` and will be treated by IBC as a simple byte string `[]byte`. It is incumbent on receiver modules to encode their acknowledgemnet in such a way that the sender module can decode it correctly. This should be decided through version negotiation during the channel handshake.
The acknowledgement may encode whether the packet processing succeeded or failed, along with additional information that will allow the sender module to take appropriate action.
Once the acknowledgement has been written by the receiving chain, a relayer will relay the acknowledgement back to the original sender module which will then execute application-specific acknowledgment logic using the contents of the acknowledgement. This may involve rolling back packet-send changes in the case of a failed acknowledgement (refunding senders).
Once an acknowledgement is received successfully on the original sender the chain, the IBC module deletes the corresponding packet commitment as it is no longer needed.
## Further Readings and Specs
If you want to learn more about IBC, check the following specifications: