数据包处理器规范定义了实现必须强制执行的语义和行为,以支持 IBC v2 协议。

数据包结构

在跨链通信协议中,Packet 是应用向其他链上的对手方应用发送数据的主要接口。其定义如下:
interface Packet {
    sourceClientId: bytes // identifier of the client on the sending chain
    destClientId: bytes // identifier of the client on the receiving chain
    sequence: uint64 // unique number identifying this packet in the stream of packets from sourceClientId to destClientId
    timeoutTimestamp: uint64, // indicates the timeout as a UNIX timestamp in seconds. If the timeout timestamp is reached on destination chain, it is no longer receivable
    data: Payload[] // a list of payloads intended for applications on the receiving chain
}
interface Payload {
    sourcePort: bytes, // identifier of the sending application on the sending chain
    destPort: bytes, // identifier of the receiving application on the receiving chain
    version: string, // payload version only interpretable by sending/receiving applications
    encoding: string, // payload encoding only interpretable by sending/receiving applications
    value: bytes // application-specific data that can be parsed by receiving application given the version and encoding
}
数据包本身不会被直接序列化并发送到对手方链。相反,会按照 ICS-24 的定义,在该数据包的标准化唯一键下存储一个针对数据包数据的标准化、不可篡改承诺。因此,只要在写入可证明存储时遵循 IBC 协议定义的标准化承诺,实现就可以自行选择内部使用的具体数据包结构和序列化方案。 数据包不变量:
  • 数据包中的任何字段都不能为空
  • 对于包含的每个负载,负载中的任何字段都不能为空

回执

Receipt 是一个哨兵字节。当接收链成功接收到某个数据包时,会将其存储在该数据包标准化的、可证明的 ReceiptPath 下。这可以防止重放攻击,也能避免在发送链上对一个实际上已经被接收的数据包执行超时处理。回执的具体值并不重要,只要它不为空即可。

确认结构

Acknowledgement 是接收应用用于向发送方返回应用特定信息的接口。如果所有应用都成功接收了各自的负载,则每个接收应用都会返回其自定义确认字节,并将其追加到确认数组中。如果任意应用返回错误,则确认中将只包含一个元素,即哨兵错误确认。
const ErrorAcknowledgement = sha256("UNIVERSAL_ERROR_ACKNOWLEDGEMENT")

interface Acknowledgement {
    appAcknowledgement bytes[] // array of an array of bytes. Each element of the array contains an acknowledgement from a specific application
}
确认不变量:
  • 如果确认接口包含错误确认,则数组中必须且只能有一个元素,即该错误确认
  • 不允许存在多个应用确认且其中某个元素为错误确认
  • 如果存在多个应用确认,则应用确认的长度必须与关联数据包中的负载数量相同,并且每个确认都与负载数组中相同位置的负载一一对应。

SendPacket

SendPacket 由用户调用,用于执行跨链流程。用户会提交一条消息,其中包含要与各个 IBC 应用交互的一个或多个负载。SendPacket 处理器必须根据负载中的 sourcePort,调用每个发送应用的 sendPacket 逻辑。如果所有发送应用都没有报错,则 SendPacket 处理器必须使用用户提供的 sourceClient、负载列表和超时信息,以及根据 sourceClient 从对手方存储中获取的 destinationClient,并为该 sourceClientId 生成一个唯一序列号来构造数据包。随后,它将在 ICS24 路径下使用 ICS24 承诺函数对该数据包进行承诺。发送链可以选择在可证明存储中使用自定义前缀来存储 ICS24 路径。在这种情况下,对手方必须知道该自定义前缀,该前缀由中继者在初始化时提供。发送链应当依据经过认证的时间预言机(本地 BFT 时间或目标客户端的最新时间戳)检查所提供的时间戳,并预先拒绝用户提供的、其时间戳已经过期的数据包。 用户可以是链下进程,也可以是链上参与者。无论哪种情况,用户都不受 IBC 协议信任。IBC 应用负责正确认证该用户是否有权使用负载 sourcePort 中指定的 IBC 应用端口发送所请求的应用数据。IBC 应用还负责执行在发送 IBC 数据包之前必须运行的任何应用特定逻辑(例如,在发送同质化代币转账数据包之前先托管用户的代币)。 SendPacket 输入: payloads: Payload[]:要从发送链上的源应用发送到接收链上对应目标应用的负载列表。实现可以选择只支持每个数据包包含单个负载。 sourceClientId: bytes:发送链上存在的、用于表示接收链的客户端标识符。 timeoutTimestamp: uint64:以 UNIX 秒表示的超时时间,超过该时间后,数据包在接收链上将不再可接收。注意:该时间戳是相对于接收链时钟进行判断的,因为发送链与接收链的时钟之间可能存在漂移。 SendPacket 前置条件:
  • 发送链上存在一个带有 sourceClientId 的有效客户端
  • 发送链上存在从 sourceClientId 到 Counterparty 的映射
SendPacket 后置条件:
  • 负载中源端口所标识的所有发送应用都已成功执行各自的 sendPacket 逻辑
  • 以下数据包会按照 ICS24 的规定,在数据包承诺路径下被承诺并存储:
interface Packet {
    sourceClientId: sourceClientId,
    destClientId: getCounterparty(sourceClientId).ClientId, // destClientId should be filled in with the registered counterparty id for provided sourceClientId
    sequence: generateUniqueSequence(sourceClientId),
    timeoutTimestamp: timeoutTimestamp
    data: payloads
}
  • 由于链上状态中存储的是数据包哈希承诺,实现必须向中继者提供数据包字段以便其重建数据包。如果实现平台具有事件系统,可以通过事件发出;如果没有事件系统,则可以在辅助键下将完整数据包存入状态中。
SendPacket 错误条件:
  • 任意发送应用在执行其 sendPacket 逻辑期间返回错误
  • 发送客户端无效(已过期或已冻结)
SendPacket 不变量:
  • sourceClientId 必须存在于发送链上
  • destClientId 必须是发送链上 sourceClientId 已注册的对手方
  • 对于相同的 sourceClientId 和 sequence,发送链之前不得发送过数据包

RecvPacket

RecvPacket 由中继者在发送链上完成数据包承诺后调用,用于在接收链上处理该数据包。由于中继者不受信任,因此中继者必须提供一个证明,证明发送链确实已经承诺了所提供的数据包;该证明将在接收链上的 destClient 上进行验证。 如果证明验证成功,并且数据包通过了重放与超时检查,那么每个负载都会作为接收应用回调的一部分发送给对应的接收应用。 RecvPacket 输入: packet: Packet:从发送链发送到本链的数据包 proof: bytes:一个不透明证明,将被发送给目标客户端。目标客户端负责将这些字节解释为证明,并根据所提供的证明来验证数据包处理器给出的数据包承诺键值。 proofHeight: Number:生成该证明时对手方链的高度。目标客户端上必须存在该高度对应的共识状态,证明才能被正确验证。 RecvPacket 前置条件:
  • 接收链上存在一个带有 destClientId 的有效客户端
  • 存在从 destClientId 到 Counterparty 的映射
RecvPacket 后置条件:
  • 在指定的 ICS24 路径下,使用 destClientId 和 sequence 存储一份数据包回执
  • 负载中 destPort 所标识的所有接收应用都已执行其 recvPacket 逻辑。如果任意负载在处理过程中返回错误,则所有负载对应的所有应用状态变更都必须回滚。如果所有负载都处理成功,则所有应用状态变更都会被写入。这可确保同一个数据包中批量打包的多个负载具备原子执行语义。
  • 如果任意负载返回错误,则通过 WriteAcknowledgment 写入单个 SENTINEL ERROR ACKNOWLEDGEMENT。如果所有负载都成功并返回应用特定确认,则每个应用确认都必须以其对应负载在数据包中出现的精确顺序,写入最终数据包 Acknowledgement 的 AppAcknowledgement 列表中。
注意:应用可能会异步处理其负载,而不是在 RecvPacket 交易执行期间同步完成。在这种情况下,IBC 核心处理器必须等待所有应用返回各自的应用确认之后,才能写入确认;并且写入时应用确认的顺序必须与其对应负载在原始数据包中的顺序一致,而不是应用异步返回确认的顺序,因为两者可能不同。IBC 允许将多个面向同一应用的负载批量放入同一个数据包中。因此,如果某个实现希望同时支持多负载和异步确认,那么核心 IBC 必须能够知道某条确认对应的是哪个负载。这可以通过在 recvPacket 应用回调期间提供负载列表中的索引来实现,使得应用在写入确认时返回相同索引,从而确保确认被放置到正确顺序。否则,实现也可以直接禁止多负载数据包的异步确认支持。 RecvPacket 错误条件:
  • Counterparty.ClientId != packet.sourceClientId,用于确保数据包来自预期的对手方
  • packet.TimeoutTimestamp >= chain.BlockTime(),用于确保当数据包在发送链上可被超时时,接收链不能成功接收该数据包
  • 对于 destClientId 和 sequence,状态中尚不存在数据包回执。这可以防止重放攻击
  • 成员证明验证失败

WriteAcknowledgement

WriteAcknowledgement 输入: destClientId: bytes:存在于接收链上的发送链客户端标识符 sequence: uint64:用于标识从发送链到接收链的数据包的唯一序列号 ack: Acknowledgement:接收链在各接收应用分别返回各自确认后,从所有接收应用收集到的确认。如果任何单个应用报错,则整个确认 MUST 仅包含一个元素,即 SENTINEL ERROR ACKNOWLEDGEMENT。如果所有应用都成功接收,则每个应用都必须在 Acknowledgement 中写入其各自的确认,且顺序必须与它们在发送数据包负载中的出现顺序一致。 WriteAcknowledgement 前置条件:
  • 在指定的 ICS24 路径下,已使用 destClientId 和 sequence 存储了一个数据包回执
  • 针对 destClientId 和 sequence 的确认尚未写入 ICS24 路径
WriteAcknowledgement 后置条件:
  • 确认已提交,并按照 ICS24 的规定写入确认路径
  • 由于确认会被哈希处理,应当提供完整的确认字段,以便中继者重建确认。如果实现平台没有事件系统,则可以通过事件系统发出这些字段,或使用辅助键将其作为完整数据包存储在状态中。
  • 实现者 SHOULD 在 WriteAcknowledgement 中再次发出完整数据包,因为发送链通常只会存储数据包承诺而不是完整数据包;中继者需要将该数据包带回发送链以处理确认。因此,为了支持无状态中继者,在 WriteAcknowledgement 中重新发出数据包字段会很有帮助,这样中继者就可以重建数据包。
  • 如果确认成功,则所有接收应用都必须已执行其 recvPacket 逻辑并写入状态
  • 如果确认不成功(即 ERROR ACK),则接收应用所做的任何状态变更都 MUST 全部回滚。这可确保多负载数据包的原子执行。

AcknowledgePacket

AcknowledgePacket 输入: packet: Packet:最初由本链发送的数据包 acknowledgement: Acknowledgement:接收链为该数据包写入的确认 proof: bytes:将发送给源客户端的不透明证明。源客户端负责解释该证明,并根据数据包处理程序提供的确认键/值对其进行验证。 proofHeight: Number:生成该证明时对手链的高度。源客户端上必须存在该高度对应的共识状态,证明才能被正确验证。 AcknowledgePacket 前置条件:
  • 发送链上存在一个与 sourceClientId 对应的有效客户端
  • 发送链上存在从 sourceClientId 到 Counterparty 的映射
  • 在 ICS24 数据包路径下,已使用 sourceClientId 和 sequence 存储了一个数据包承诺
AcknowledgePacket 后置条件:
  • 所有发送应用都会使用负载,以及该负载对应的单独确认或通用的 ErrorAcknowledgement,执行 ackPacket 逻辑。
  • 已存储的数据包承诺被删除
AcknowledgePacket 错误条件:
  • packet.destClient != counterparty.ClientId。如果第二个错误条件不成立,这种情况理论上不应发生,因为我们之前已正确构造了该数据包
  • 中继者提供的数据包,与我们为 sourceClientId 和 sequence 存储的承诺不匹配
  • 按 ICS24 标准定义的、接收链上确认承诺的成员证明验证失败
  • 任一应用在其负载对应的 AcknowledgePacket 回调期间返回错误。通常应用不应在 AcknowledgePacket 上报错。如果发生这种情况,极有可能是一个 bug,因此该错误应回滚交易,并在重新提交交易前修复该 bug。

TimeoutPacket

TimeoutPacket 输入: packet: Packet:最初由本链发送的数据包 proof: bytes:将发送给源客户端的不透明不存在性证明。源客户端负责解释该证明,并根据数据包处理程序提供的回执键对其进行验证。 proofHeight: Number:生成该证明时对手链的高度。源客户端上必须存在该高度对应的共识状态,证明才能被正确验证。 TimeoutPacket 前置条件:
  • 发送链上存在一个与 sourceClientId 对应的有效客户端
  • 发送链上存在从 sourceClientId 到 Counterparty 的映射
  • 在 ICS24 数据包路径下,已使用 sourceClientId 和 sequence 存储了一个数据包承诺
TimeoutPacket 后置条件:
  • 所有发送应用都会使用该负载执行 timeoutPacket 逻辑。
  • 已存储的数据包承诺被删除
TimeoutPacket 错误条件:
  • packet.destClient != counterparty.ClientId。如果第二个错误条件不成立,这种情况理论上不应发生,因为我们之前已正确构造了该数据包
  • 中继者提供的数据包,与我们为 sourceClientId 和 sequence 存储的承诺不匹配
  • 按 ICS24 标准定义的、接收链上数据包回执的非成员证明验证失败
  • 任一应用在其负载对应的 TimeoutPacket 回调期间返回错误。通常应用不应在 TimeoutPacket 上报错。如果发生这种情况,极有可能是一个 bug,因此该错误应回滚交易,并在重新提交交易前修复该 bug。

The packet handler specification defines the semantics and behavior that implementations must enforce in order to support IBC v2 protocol.

Packet Structure

A Packet in the interblockchain communication protocol is the primary interface by which applications will send data to counterparty applications on other chains. It is defined as follows:
interface Packet {
    sourceClientId: bytes // identifier of the client on the sending chain
    destClientId: bytes // identifier of the client on the receiving chain
    sequence: uint64 // unique number identifying this packet in the stream of packets from sourceClientId to destClientId
    timeoutTimestamp: uint64, // indicates the timeout as a UNIX timestamp in seconds. If the timeout timestamp is reached on destination chain, it is no longer receivable
    data: Payload[] // a list of payloads intended for applications on the receiving chain
}
interface Payload {
    sourcePort: bytes, // identifier of the sending application on the sending chain
    destPort: bytes, // identifier of the receiving application on the receiving chain
    version: string, // payload version only interpretable by sending/receiving applications
    encoding: string, // payload encoding only interpretable by sending/receiving applications
    value: bytes // application-specific data that can be parsed by receiving application given the version and encoding
}
The packet is never directly serialised and sent to counterparty chains. Instead a standardized non-malleable committment to the packet data is stored under the standardized unique key for the packet as defined in ICS-24. Thus, implementations MAY make individual choices on the exact packet structure and serialization scheme they use internally so long as they respect the standardized commitment defined by the IBC protocol when writing to the provable store. Packet Invariants:
  • None of the packet fields are allowed to be empty
  • For every payload included, none of the payload fields are allowed to be empty

Receipt

A Receipt is a sentinel byte that is stored under the standardized provable ReceiptPath of a given packet by the receiving chain when it successfully receives the packet. This prevents replay attacks and also the possibility of timing out a packet on the sender chain when the packet has already been received. The specific value of the receipt does not matter so long as its not empty.

Acknowledgement Structure

An Acknowledgement is the interface that will be used by receiving applications to return application specific information back to the sender. If every application successfully received its payload, then each receiving application will return their custom acknowledgement bytes which will be appended to the acknowledgement array. If any application returns an error, then the acknowledgement will have a single element with a sentinel error acknowledgement.
const ErrorAcknowledgement = sha256("UNIVERSAL_ERROR_ACKNOWLEDGEMENT")

interface Acknowledgement {
    appAcknowledgement bytes[] // array of an array of bytes. Each element of the array contains an acknowledgement from a specific application
}
Acknowledgement Invariants:
  • If the acknowledgement interface includes an error acknowledgement then there must be only a single element in the array with the error acknowledgement
  • There CANNOT be multiple app acknowledgements where an element is the error acknowledgement
  • If there are multiple app acknowledgements, the length of the app acknowledgements is the same length as the payloads in the associated packet and each acknowledgement is associated with the payload in the same position in the payload array.

SendPacket

SendPacket is called by users to execute an inter-blockchain flow. The user submits a message with a payload(s) for each IBC application they wish to interact with. The SendPacket handler must call the sendPacket logic of each sending application as identified by the sourcePort of the payload. If none of the sending applications error, then the sendPacket handler must construct the packet with the user-provided sourceClient, payloads, and timeout and the destinationClient it retrieves from the counterparty storage given the sourceClient and a generated sequence that is unique for the sourceClientId. It will commit the packet with the ICS24 commitment function under the ICS24 path. The sending chain MAY store the ICS24 path under a custom prefix in the provable store. In this case, the counterparty must have knowledge of the custom prefix as provided by the relayer on setup. The sending chain SHOULD check the provided timestamp against an authenticated time oracle (local BFT time or destination client latest timestamp) and preemptively reject a user-provided packet with a timestamp that has already passed. The user may be an off-chain process or an on-chain actor. In either case, the user is not trusted by the IBC protocol. The IBC application is responsible for properly authenticating that the user is allowed to send the requested app data using the IBC application’s port as specified in the source port of the payload. The IBC application is also responsible for executing any app-specific logic that must run before the IBC packet can be sent (e.g. escrowing user’s tokens before sending a fungible token transfer packet). SendPacket Inputs: payloads: Payload[]: List of payloads that are to be sent from source applications on sending chain to corresponding destination applications on the receiving chain. Implementations MAY choose to only support a single payload per packet. sourceClientId: bytes: Identifier of the receiver chain client that exists on the sending chain. timeoutTimestamp: uint64: The timeout in UNIX seconds after which the packet is no longer receivable on the receiving chain. NOTE: This timestamp is evaluated against the receiving chain clock as there may be drift between the sending chain and receiving chain clocks SendPacket Preconditions:
  • A valid client exists on the sending chain with the sourceClientId
  • There exists a mapping on the sending chain from sourceClientId to Counterparty
SendPacket Postconditions:
  • The sending application(s) as identified by the source port(s) in the payload(s) have all executed their sendPacket logic successfully
  • The following packet gets committed and stored under the packet commitment path as specified by ICS24:
interface Packet {
    sourceClientId: sourceClientId,
    destClientId: getCounterparty(sourceClientId).ClientId, // destClientId should be filled in with the registered counterparty id for provided sourceClientId
    sequence: generateUniqueSequence(sourceClientId),
    timeoutTimestamp: timeoutTimestamp
    data: payloads
}
  • Since the packet is committed to with a hash in-state, implementations must provide the packet fields for relayers to reconstruct. This can be emitted in an event system or stored in state as the full packet under an auxilliary key if the implementing platform does not have an event system.
SendPacket Errorconditions:
  • Any of the sending applications returns an error during its sendPacket logic execution
  • The sending client is invalid (expired or frozen)
SendPacket Invariants:
  • The sourceClientId MUST exist on the sending chain
  • The destClientId MUST be the registered counterparty of the sourceClientId on the sending chain
  • The sending chain MUST NOT have sent a previous packet with the same sourceClientId and sequence

RecvPacket

RecvPacket is called by relayers once a packet has been committed on the sender chain in order to process the packet on the receiving chain. Since the relayer is not trusted, the relayer must provide a proof that the sender chain had indeed committed the provided packet which will be verified against the destClient on the receiving chain. If the proof succeeds, and the packet passes replay and timeout checks; then each payload is sent to the receiving application as part of the receiving application callback. RecvPacket Inputs: packet: Packet: The packet sent from the sending chain to our chain proof: bytes: An opaque proof that will be sent to the destination client. The destination client is responsible for interpreting the bytes as a proof and verifying the packet commitment key/value provided by the packet handler against the provided proof. proofHeight: Number: This is the height of the counterparty chain from which the proof was generated. A corresponding consensus state for this height must exist on the destination client for the proof to verify correctly. RecvPacket Preconditions:
  • A valid client exists on the receiving chain with destClientId
  • There exists a mapping from destClientId to Counterparty
RecvPacket Postconditions:
  • A packet receipt is stored under the specified ICS24 with the destClientId and sequence
  • All receiving application(s) as identified by the destPort(s) in the payload(s) have executed their recvPacket logic. If any of the payloads return an error during processing, then all application state changes for all payloads must be reverted. If all payloads are processed successfully, then all applications state changes are written. This ensures atomic execution for the payloads batched together in a single packet.
  • If any payload returns an error, then the single SENTINEL ERROR ACKNOWLEDGEMENT is written using WriteAcknowledgment. If all payloads succeed and return an app-specific acknowledgement, then each app acknowledgement is included in the list of AppAcknowledgement in the final packet Acknowledgement in the exact order that their corresponding payloads were included in the packet.
NOTE: It is possible for applications to process their payload asynchronously to the RecvPacket transaction execution. In this case, the IBC core handler must await all applications returning their individual application acknowledgements before writing the acknowledgement with app acknowledgements in the order of their corresponding payloads in the original packet not the order in which the applications return their asynchronous acknowledgements which may be different orders. IBC allows multiple payloads intended for the same application to be batched in the same packet. Thus, if an implementation wishes to support multiple payloads and asynchronous acknowledgements together, then there must be a way for core IBC to know which payload a particular acknowledgment is being written for. This may be done by providing the index of the payload list during recvPacket application callback, so that the application can return the same index when writing the acknowledgment so that it can be placed in the right order. Otherwise, implementations may simply block asynchronous acknowledgment support for multi-payload packets RecvPacket Errorconditions:
  • Counterparty.ClientId != packet.sourceClientId ensures that packet was sent by expected counterparty
  • packet.TimeoutTimestamp >= chain.BlockTime() ensures we cannot receive successfully if packet can be timed out on sending chain
  • Packet receipt does not already exist in state for the destClientId and sequence. This prevents replay attacks
  • Membership proof does not successfully verify

WriteAcknowledgement

WriteAcknowledgement Inputs: destClientId: bytes: Identifier of the sender chain client that exist on the receiving chain sequence: uint64: Unique sequence identifying the packet from sending chain to receiving chain ack: Acknowledgement: Acknowledgement collected by receiving chain from all receiving applications after they have returned their individual acknowledgement. If any individual application errors, the entire acknowledgement MUST have a single element with just the SENTINEL ERROR ACKNOWLEDGEMENT. If all applications successfully received, then every application must have its own acknowledgement set in the Acknowledgement in the same order that they existed in the payload of the sending packet. WriteAcknowledgement Preconditions:
  • A packet receipt is stored under the specified ICS24 with the destClientId and sequence
  • An acknowledgement for the destClientId and sequence has not already been written under the ICS24 path
WriteAcknowledgement Postconditions:
  • The acknowledgement is committed and written to the acknowledgement path as specified in ICS24
  • Since the acknowledgement is being hashed, the full acknowledgement fields should be made available for relayers to reconstruct. This can be emitted in an event system or stored in state as the full packet under an auxilliary key if the implementing platform does not have an event system.
  • Implementors SHOULD also emit the full packet again in WriteAcknowledgement since the sender chain is only expected to store the packet commitment and not the full packet; relayers are expected to pass the packet back to the sender chain to process the acknowledgement. Thus, in order to support stateless relayers it is helpful to re-emit the packet fields on WriteAcknowledgement so the relayer can reconstruct the packet.
  • If the acknowledgement is successful, then all receiving applications must have executed their recvPacket logic and written state
  • If the acknowledgement is unsuccessful (ie ERROR ACK), any state changes made by the receiving applications MUST all be reverted. This ensure atomic execution of the multi-payload packet.

AcknowledgePacket

AcknowledgePacket Inputs: packet: Packet: The packet that was originally sent by our chain acknowledgement: Acknowledgement: The acknowledgement written by the receiving chain for the packet proof: bytes: An opaque proof that will be sent to the source client. The source client is responsible for interpreting the proof and verifying it against the acknowledgement key/value provided by the packet handler. proofHeight: Number: This is the height of the counterparty chain from which the proof was generated. A corresponding consensus state for this height must exist on the source client for the proof to verify correctly. AcknowledgePacket Preconditions:
  • A valid client exists on the sending chain with the sourceClientId
  • There exists a mapping on the sending chain from sourceClientId to Counterparty
  • A packet commitment has been stored under the ICS24 packet path with sourceClientId and sequence
AcknowledgePacket Postconditions:
  • All sending applications execute the ackPacket logic with the payload and the individual acknowledgement for that payload or the universal ErrorAcknowledgement.
  • Stored commitment for the packet is deleted
AcknowledgePacket Errorconditions:
  • packet.destClient != counterparty.ClientId. This should never happen if the second error condition is not true, since we constructed the packet correctly earlier
  • The packet provided by the relayer does not commit to the stored commitment we have stored for the sourceClientId and sequence
  • Membership proof of the acknowledgement commitment on the receiving chain as standardized by ICS24 does not verify
  • Any of the applications return an error during the AcknowledgePacket callback for their payload. Applications should generally not error on AcknowledgePacket. If this occurs, it is most likely a bug so the error should revert the transaction and allow for the bug to be patched before resubmitting the transaction.

TimeoutPacket

TimeoutPacket Inputs: packet: Packet: The packet that was originally sent by our chain proof: bytes: An opaque non-existence proof that will be sent to the source client. The source client is responsible for interpreting the proof and verifying it against the receipt key provided by the packet handler. proofHeight: Number: This is the height of the counterparty chain from which the proof was generated. A corresponding consensus state for this height must exist on the source client for the proof to verify correctly. TimeoutPacket Preconditions:
  • A valid client exists on the sending chain with the sourceClientId
  • There exists a mapping on the sending chain from sourceClientId to Counterparty
  • A packet commitment has been stored under the ICS24 packet path with sourceClientId and sequence
TimeoutPacket Postconditions:
  • All sending applications execute the timeoutPacket logic with the payload.
  • Stored commitment for the packet is deleted
TimeoutPacket Errorconditions:
  • packet.destClient != counterparty.ClientId. This should never happen if the second error condition is not true, since we constructed the packet correctly earlier
  • The packet provided by the relayer does not commit to the stored commitment we have stored for the sourceClientId and sequence
  • Non-Membership proof of the packet receipt on the receiving chain as standardized by ICS24 does not verify
  • Any of the applications return an error during the TimeoutPacket callback for their payload. Applications should generally not error on TimeoutPacket. If this occurs, it is most likely a bug so the error should revert the transaction and allow for the bug to be patched before resubmitting the transaction.