icacontroller 和 x/wasm 之类的次级应用,可以跳过本节。
开发底层 IBC 应用所需的接口
PacketDataUnmarshaler
PacketDataUnmarshaler 接口,以便它能够将数据包数据字节反序列化为合适的数据包数据类型。这样就可以使用该数据包数据类型所实现的接口函数。这里预期数据包数据类型会实现 PacketDataProvider 接口(见下文),该接口用于解析当前以 JSON 字符串形式存储在 transfer 和 ica 数据包 memo 字段中的回调数据。可参考其在 transfer 和 icacontroller 模块中的实现。
如果底层应用本身也是一个中间件,那么它可以通过简单地将函数调用传递给其底层应用来实现该接口。可参考 fee middleware 中的实现。
PacketDataProvider
PacketDataProvider 接口。该接口用于从数据包数据中获取回调数据(对于 transfer 和 ica,使用的是 memo 字段)。例如,可参考其在 transfer 模块中的实现。
由于中间件没有数据包类型,因此不需要实现该接口。
PacketData
PacketData 是一个可选接口,底层 ibc 应用的数据包数据类型可以实现它。它用于从数据包数据中获取数据包发送方地址。回调中间件会在源端回调期间使用该接口获取数据包发送方地址,并将其传递给回调函数。如果未实现该接口,则回调中间件会将空字符串作为发送方地址传递。例如,可参考其在 transfer 和 ica 模块中的实现。
添加该接口是为了让次级应用在需要时能够获取数据包发送方地址,以执行自定义授权逻辑。
由于中间件没有数据包类型,因此不需要实现该接口。
开发次级应用所需的接口
ContractKeeper
callbacks 中间件要求次级应用实现 ContractKeeper 接口。合约 keeper 会在数据包生命周期的每个阶段被调用。当数据包被发送时,如果提供了回调信息,合约 keeper 将通过 IBCSendPacketCallback 被调用。这使合约 keeper 能够在提供回调信息时阻止数据包发送,例如发送者未被授权基于给定信息执行回调。如果数据包发送成功,则目标链上的合约 keeper(如果存在)会在数据包被接收且确认写入后被调用,这会通过 IBCReceivePacketCallback 发生。在数据包生命周期的最后阶段,处理确认或超时时,源链合约 keeper 会通过 IBCOnAcknowledgementPacket 或 IBCOnTimeoutPacket 被调用。数据包一旦发送,只要 relayer 将 gas 限制设置为大于或等于所需的 CommitGasLimit,生命周期中的每个步骤都可以被处理。在回调中执行的状态变更只有在成功执行后才会被提交。
The callbacks middleware requires certain interfaces to be implemented by the underlying IBC applications and the secondary application. If you’re simply wiring up the callbacks middleware to an existing IBC application stack and a secondary application such as
icacontroller and x/wasm, you can skip this section.
Interfaces for developing the Underlying IBC Application
PacketDataUnmarshaler
PacketDataUnmarshaler interface so that it can unmarshal the packet data bytes into the appropriate packet data type. This allows usage of interface functions implemented by the packet data type. The packet data type is expected to implement the PacketDataProvider interface (see section below), which is used to parse the callback data that is currently stored in the packet memo field for transfer and ica packets as a JSON string. See its implementation in the transfer and icacontroller modules for reference.
If the underlying application is a middleware itself, then it can implement this interface by simply passing the function call to its underlying application. See its implementation in the fee middleware for reference.
PacketDataProvider
PacketDataProvider interface. This interface is used to retrieve the callback data from the packet data (using the memo field in the case of transfer and ica). For example, see its implementation in the transfer module.
Since middlewares do not have packet types, they do not need to implement this interface.
PacketData
PacketData is an optional interface that can be implemented by the underlying ibc application’s packet data type. It is used to retrieve the packet sender address from the packet data. The callbacks middleware uses this interface to retrieve the packet sender address and pass it to the callback function during a source callback. If this interface is not implemented, then the callbacks middleware passes and empty string as the sender address. For example, see its implementation in the transfer and ica module.
This interface was added so that secondary applications can retrieve the packet sender address to perform custom authorization logic if needed.
Since middlewares do not have packet types, they do not need to implement this interface.
Interfaces for developing the Secondary Application
ContractKeeper
The callbacks middleware requires the secondary application to implement the ContractKeeper interface. The contract keeper will be invoked at each step of the packet lifecycle. When a packet is sent, if callback information is provided, the contract keeper will be invoked via the IBCSendPacketCallback. This allows the contract keeper to prevent packet sends when callback information is provided, for example if the sender is unauthorized to perform callbacks on the given information. If the packet send is successful, the contract keeper on the destination (if present) will be invoked when a packet has been received and the acknowledgement is written, this will occur via IBCReceivePacketCallback. At the end of the packet lifecycle, when processing acknowledgements or timeouts, the source contract keeper will be invoked either via IBCOnAcknowledgementPacket or IBCOnTimeoutPacket. Once a packet has been sent, each step of the packet lifecycle can be processed given that a relayer sets the gas limit to be more than or equal to the required CommitGasLimit. State changes performed in the callback will only be committed upon successful execution.