diff --git a/spec/core/v2/ics-004-channel-and-packet-semantics/README.md b/spec/core/v2/ics-004-channel-and-packet-semantics/README.md
index 4d8d80430..8ab7fedaa 100644
--- a/spec/core/v2/ics-004-channel-and-packet-semantics/README.md
+++ b/spec/core/v2/ics-004-channel-and-packet-semantics/README.md
@@ -162,8 +162,8 @@ The ICS-04 use the protocol paths, defined in [ICS-24](../ics-024-host-requireme
Thus, constant-size commitments to packet data fields are stored under the packet sequence number:
```typescript
-function packetCommitmentPath(channelSourceId: bytes, sequence: BigEndianUint64): Path {
- return "{channelSourceId}|0x1|{bigEndianUint64Sequence}"
+function packetCommitmentPath(sourceChannel: bytes, sequence: BigEndianUint64): Path {
+ return "{sourceChannel}|0x1|{bigEndianUint64Sequence}"
}
```
@@ -172,16 +172,16 @@ Absence of the path in the store is equivalent to a zero-bit.
Packet receipt data are stored under the `packetReceiptPath`. In the case of a successful receive, the destination chain writes a sentinel success value of `SUCCESSFUL_RECEIPT`.
```typescript
-function packetReceiptPath(channelDestId: bytes, sequence: BigEndianUint64): Path {
- return "{channelDestId}|0x2|{bigEndianUint64Sequence}"
+function packetReceiptPath(destChannel: bytes, sequence: BigEndianUint64): Path {
+ return "{destChannel}|0x2|{bigEndianUint64Sequence}"
}
```
Packet acknowledgement data are stored under the `packetAcknowledgementPath`:
```typescript
-function packetAcknowledgementPath(channelSourceId: bytes, sequence: BigEndianUint64): Path {
- return "{channelSourceId}|0x3|{bigEndianUint64Sequence}"
+function packetAcknowledgementPath(sourceChannel: bytes, sequence: BigEndianUint64): Path {
+ return "{sourceChannel}|0x3|{bigEndianUint64Sequence}"
}
```
@@ -296,36 +296,36 @@ function createChannel(
clientId: bytes,
counterpartyKeyPrefix: CommitmentPrefix): bytes {
- // Implementation-Specific Input Validation
- // All implementations MUST ensure the inputs value are properly validated and compliant with this specification
- client=getClient(clientId)
- assert(client!==null)
- assert(isFormatOk(counterpartyKeyPrefix))
+ // Implementation-Specific Input Validation
+ // All implementations MUST ensure the inputs value are properly validated and compliant with this specification
+ client=getClient(clientId)
+ assert(client!==null)
+ assert(isFormatOk(counterpartyKeyPrefix))
- // Channel Checks
- channelId = generateIdentifier()
- abortTransactionUnless(validateIdentifier(channelId))
- abortTransactionUnless(getChannel(channelId)) === null)
-
- // Channel manipulation
- channel = Channel{
- clientId: clientId,
- counterpartyChannelId: "", // This field it must be a blank field during the creation as it may be not known at the creation time.
- keyPrefix: counterpartyKeyPrefix
- }
+ // Channel Checks
+ channelId = generateIdentifier()
+ abortTransactionUnless(validateIdentifier(channelId))
+ abortTransactionUnless(getChannel(channelId)) === null)
+
+ // Channel manipulation
+ channel = Channel{
+ clientId: clientId,
+ counterpartyChannelId: "", // This field it must be a blank field during the creation as it may be not known at the creation time.
+ keyPrefix: counterpartyKeyPrefix
+ }
- // Local stores
- // Store channel info
- storedChannels[channelId]=channel
- // Store creator address info
- channelCreator[channelId]=msg.signer()
- // Initialise the nextSequenceSend
- nextSequenceSend[channelId]=1
-
- // Event Emission
- emitLogEntry("createChannel", {
+ // Local stores
+ // Store channel info
+ storedChannels[channelId]=channel
+ // Store creator address info
+ channelCreator[channelId]=msg.signer()
+ // Initialise the nextSequenceSend
+ nextSequenceSend[channelId]=1
+
+ // Event Emission
+ emitEvents("createChannel", {
channelId: channelId,
- channel: channel,
+ clientId: clientId,
creatorAddress: msg.signer(),
})
@@ -377,10 +377,10 @@ function registerCounterparty(
// log that a packet can be safely sent
// Event Emission
- emitLogEntry("registerCounterparty", {
- channelId: channelId,
- channel: channel,
- creatorAddress: msg.signer(),
+ emitEvents("registerCounterparty", {
+ channelId: channelId,
+ clientId: channel.clientId
+ counterpartyChannelid: counterpartyChannelId,
})
}
```
@@ -513,7 +513,7 @@ sequenceDiagram
##### Sending packets
-The `sendPacket` function is called by the IBC handler when an IBC packet is submitted to the newtwork in order to send *data* in the form of an IBC packet. The `sendPacket` function executes the IBC core logic and atomically triggers the application logic execution via the activation of the `onSendPacket` callback. Indeed ∀ `Payload` included in the `packet.data`, which refers to a specific application, the callbacks are retrieved from the IBC router and the `onSendPacket` is the then triggered on the application specified in the `payload` content. Once all payloads contained in the `packet.data` have been processed, the packet commitment is generated and the sequence number bound to the `channelSourceId` is incremented.
+The `sendPacket` function is called by the IBC handler when an IBC packet is submitted to the newtwork in order to send *data* in the form of an IBC packet. The `sendPacket` function executes the IBC core logic and atomically triggers the application logic execution via the activation of the `onSendPacket` callback. Indeed ∀ `Payload` included in the `packet.data`, which refers to a specific application, the callbacks are retrieved from the IBC router and the `onSendPacket` is the then triggered on the application specified in the `payload` content. Once all payloads contained in the `packet.data` have been processed, the packet commitment is generated and the sequence number bound to the `sourceChannel` is incremented.
The `sendPacket` core function MUST execute the applications logic atomically triggering the `onSendPacket` callback ∀ application contained in the `packet.data` payload.
@@ -564,7 +564,6 @@ function sendPacket(
// disallow packet with timeoutTimestamp less than currentTimestamp and timeoutTimestamp value bigger than currentTimestamp + MaxTimeoutDelta
assert(currentTimestamp() < timeoutTimestamp < currentTimestamp() + MAX_TIMEOUT_DELTA)
-
// retrieve sequence
sequence = nextSequenceSend[sourecChannelId]
// Check that the Sequence has been correctly initialized before hand.
@@ -582,12 +581,12 @@ function sendPacket(
// Construct the packet
packet = Packet {
- sourceId: sourceChannelId,
- destId: channel.counterpartyChannelId,
- sequence: sequence,
- timeoutTimestamp: timeoutTimestamp,
- payloads: payloads
- }
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence,
+ timeoutTimestamp: timeoutTimestamp,
+ payloads: payloads
+ }
// store packet commitment using commit function defined in [packet specification](https://github.com/cosmos/ibc/blob/c7b2e6d5184b5310843719b428923e0c5ee5a026/spec/core/v2/ics-004-packet-semantics/PACKET.md)
commitment=commitV2Packet(packet)
@@ -596,15 +595,33 @@ function sendPacket(
// increment the sequence. Thus there are monotonically increasing sequences for packet flow for a given clientId
nextSequenceSend[sourceChannelId]=sequence+1
- // log that a packet can be safely sent
- // Event Emission
- emitLogEntry("sendPacket", {
- sourceId: sourceChannelId,
- destId: channel.counterpartyChannelId,
- sequence: sequence,
- packet: packet,
- timeoutTimestamp: timeoutTimestamp,
+ // Event Emission for send packet
+ emitEvents("send_packet", {
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence, // value is string in decimal format
+ timeoutTimestamp: timeoutTimestamp, // value is string in decimal format
+ payloadLength: len(payloads), // value is string in decimal format
+ // include first payload data in events if there is only one payload
+ version: payload[0].version,
+ encoding: payload[0].encoding,
+ data: toHex(payload[0].appData) // emit app bytes as string in hex format
})
+
+ // for multi payload cases, we will emit each payload as a separate event
+ // these will include the packet identifier so they can be indexed and
+ // reconstructed by relayers
+ for i, payload in payloads {
+ emitEvents("send_payload", {
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence, // value is string in decimal format
+ payloadSequence: i, // value is string in payload format
+ version: payload.version,
+ encoding: payload.encoding,
+ data: toHex(payload.appData) // emit app bytes as string in hex format
+ })
+ }
return sequence
}
@@ -634,9 +651,9 @@ Pre-conditions:
| **Condition Type** | **Description** | **Code Checks** |
|-------------------------------|-----------------------------------------------|-----------------------------------------------|
-| **Error-Conditions** | 1. invalid `packetCommitment`, 2.`packetReceipt` already exists
3. Invalid timeoutTimestamp
4. Unsuccessful payload execution.
5. Unexpected counterparty channel id | 1.1 `verifyMembership(packetCommitment)==false`
1.2 `provableStore.get(packetReceiptPath(packet.channelDestId, packet.sequence))!=null`
3. `timeoutTimestamp === 0`
3.1 `currentTimestamp() > packet.timeoutTimestamp`
4. `onReceivePacket(..)==False`
5. `packet.sourceChannelId != channel.counterpartyChannelId` |
-| **Post-Conditions (Success)** | 1. `onReceivePacket` is executed and the application state is modified
2. The `packetReceipt` is written
3. Event is Emitted
| 1. `onReceivePacket(..)==True; app.State(beforeReceivePacket)!=app.State(afterReceivePacket)`
2. `provableStore.get(packetReceiptPath(packet.channelDestId, packet.sequence))!=null`
3. Check Event Emission
|
-| **Post-Conditions (Error)** | 1. if `onReceivePacket` fails the application state is unchanged
2. `packetReceipt is not written`
3. No Event Emission
| 1. `app.State(beforeReceivePacket)==app.State(afterReceivePacket)`
2. `provableStore.get(packetReceiptPath(packet.channelDestId, packet.sequence))==null`
3. Check No Event is Emitted
|
+| **Error-Conditions** | 1. invalid `packetCommitment`, 2.`packetReceipt` already exists
3. Invalid timeoutTimestamp
4. Unsuccessful payload execution.
5. Unexpected counterparty channel id | 1.1 `verifyMembership(packetCommitment)==false`
1.2 `provableStore.get(packetReceiptPath(packet.destChannel, packet.sequence))!=null`
3. `timeoutTimestamp === 0`
3.1 `currentTimestamp() > packet.timeoutTimestamp`
4. `onReceivePacket(..)==False`
5. `packet.sourceChannelId != channel.counterpartyChannelId` |
+| **Post-Conditions (Success)** | 1. `onReceivePacket` is executed and the application state is modified
2. The `packetReceipt` is written
3. Event is Emitted
| 1. `onReceivePacket(..)==True; app.State(beforeReceivePacket)!=app.State(afterReceivePacket)`
2. `provableStore.get(packetReceiptPath(packet.destChannel, packet.sequence))!=null`
3. Check Event Emission
|
+| **Post-Conditions (Error)** | 1. if `onReceivePacket` fails the application state is unchanged
2. `packetReceipt is not written`
3. No Event Emission
| 1. `app.State(beforeReceivePacket)==app.State(afterReceivePacket)`
2. `provableStore.get(packetReceiptPath(packet.destChannel, packet.sequence))==null`
3. Check No Event is Emitted
|
###### Pseudo-Code
@@ -653,7 +670,7 @@ function recvPacket(
) {
// Channel and Client Checks
- channel = getChannel(packet.channelDestId)
+ channel = getChannel(packet.destChannel)
assert(channel !== null)
client = router.clients[channel.clientId]
assert(client !== null)
@@ -666,13 +683,13 @@ function recvPacket(
assert(currentTimestamp() < packet.timeoutTimestamp)
// verify the packet receipt for this packet does not exist already
- packetReceipt = provableStore.get(packetReceiptPath(packet.channelDestId, packet.sequence))
+ packetReceipt = provableStore.get(packetReceiptPath(packet.destChannel, packet.sequence))
abortTransactionUnless(packetReceipt === null)
//////// verify commitment
// 1. retrieve keys
- packetPath = packetCommitmentPath(packet.channelDestId, packet.sequence)
+ packetPath = packetCommitmentPath(packet.destChannel, packet.sequence)
merklePath = applyPrefix(channel.keyPrefix, packetPath)
// 2. reconstruct commit value based on the passed-in packet
@@ -686,47 +703,65 @@ function recvPacket(
merklePath,
commit))
-
// Executes Application logic ∀ Payload
payload=packet.data[0]
cbs = router.callbacks[payload.destPort]
- ack,success = cbs.onReceivePacket(packet.channelDestId,packet.channelSourceId,packet.sequence,payload,relayer) // Note that payload includes the version. The application is required to inspect the version to route the data to the proper callback
+ acknowledgement,success = cbs.onReceivePacket(packet.destChannel,packet.sourceChannel,packet.sequence,payload,relayer) // Note that payload includes the version. The application is required to inspect the version to route the data to the proper callback
abortTransactionUnless(success)
if ack != nil {
// NOTE: Synchronous ack.
- writeAcknowledgement(packet.channelDestId,packet.sequence,ack)
- // In case of Synchronous ack we emit the event here as we have all the necessary information, while writeAcknowledgement can only retrieve this in case of asynchronous ack.
- emitLogEntry("writeAcknowledgement", {
- sequence: packet.sequence,
- sourceId: packet.channelSourceId,
- destId: packet.channelDestId,
- timeoutTimestamp: packet.timeoutTimestamp,
- data: packet.data,
- ack
- })
+ writeAcknowledgement(packet.destChannel,packet.sequence,ack)
+ // emit an acknowledgement event for each app acknowledgement in the acknowledgement
+ for i, ack in acknowledgment {
+ // In case of Synchronous ack we emit the event here as we have all the necessary information, while writeAcknowledgement can only retrieve this in case of asynchronous ack.
+ emitEvents("write_acknowledgement", {
+ sourceChannel: packet.sourceChannel,
+ destChannel: packet.destChannel,
+ sequence: packet.sequence, // value is string in decimal format
+ payloadSequence: i, // value is string in decimal format
+ acknowledgement: toHex(ack),
+ })
+ }
}else {
// NOTE No ack || Asynchronous ack.
// ack is nil and will be written asynchronously, so we store the full packet in the private store
- storedPacket[packet.channelDestId,packet.sequence]=packet
+ storedPacket[packet.destChannel,packet.sequence]=packet
}
// Provable Stores
// we must set the receipt so it can be verified on the other side
// it's the sentinel success receipt: []byte{0x01}
provableStore.set(
- packetReceiptPath(packet.channelDestId, packet.sequence),
+ packetReceiptPath(packet.destChannel, packet.sequence),
SUCCESSFUL_RECEIPT
)
- // log that a packet has been received
- // Event Emission
- emitLogEntry("recvPacket", {
- data: packet.data
- timeoutTimestamp: packet.timeoutTimestamp,
- sequence: packet.sequence,
- sourceId: packet.channelSourceId,
- destId: packet.channelDestId,
- relayer: relayer
+ // Event Emission for receive packet
+ emitEvents("recv_packet", {
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence, // value is string in decimal format
+ timeoutTimestamp: timeoutTimestamp, // value is string in decimal format
+ payloadLength: len(payloads), // value is string in decimal format
+ // include first payload data in events if there is only one payload
+ version: payload[0].version,
+ encoding: payload[0].encoding,
+ data: toHex(payload[0].appData) // emit app bytes as string in hex format
})
+
+ // for multi payload cases, we will emit each payload as a separate event
+ // these will include the packet identifier so they can be indexed and
+ // reconstructed by relayers
+ for i, payload in payloads {
+ emitEvents("recv_payload", {
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence, // value is string in decimal format
+ payloadSequence: i, // value is string in decimal format
+ version: payload.version,
+ encoding: payload.encoding,
+ data: toHex(payload.appData) // emit app bytes as string in hex format
+ })
+ }
}
```
@@ -754,9 +789,9 @@ Pre-conditions:
| **Condition Type** | **Description** | **Code Checks** |
|-------------------------------|------------|------------|
-| **Error-Conditions** | 1. acknowledgement is empty
2. The `packetAcknowledgementPath` stores already a value. | 1. `len(acknowledgement) === 0`
2. `provableStore.get(packetAcknowledgementPath(packet.channelDestId, packet.sequence) !== null` |
-| **Post-Conditions (Success)** | 1. opaque acknowledgement has been written at `packetAcknowledgementPath`
2. Event is Emitted
| 1. `provableStore.get(packetAcknowledgementPath(packet.channelDestId, packet.sequence) !== null`
2. Check Event Emission
|
-| **Post-Conditions (Error)** | 1. No value is stored at the `packetAcknowledgementPath`.
2. No Event is Emitted
| 1. `provableStore.get(packetAcknowledgementPath(packet.channelDestId, packet.sequence) === null`
2. Check No Event is Emitted
|
+| **Error-Conditions** | 1. acknowledgement is empty
2. The `packetAcknowledgementPath` stores already a value. | 1. `len(acknowledgement) === 0`
2. `provableStore.get(packetAcknowledgementPath(packet.destChannel, packet.sequence) !== null` |
+| **Post-Conditions (Success)** | 1. opaque acknowledgement has been written at `packetAcknowledgementPath`
2. Event is Emitted
| 1. `provableStore.get(packetAcknowledgementPath(packet.destChannel, packet.sequence) !== null`
2. Check Event Emission
|
+| **Post-Conditions (Error)** | 1. No value is stored at the `packetAcknowledgementPath`.
2. No Event is Emitted
| 1. `provableStore.get(packetAcknowledgementPath(packet.destChannel, packet.sequence) === null`
2. Check No Event is Emitted
|
###### Pseudo-Code
@@ -784,14 +819,45 @@ function writeAcknowledgement(
// Note that the event should be emitted by this function only in the asynchrounous ack case. Otherwise the event is emitted during the onReceive
packet=getPacket(destChannelId,sequence)
if(packet!=nil){
- emitLogEntry("writeAcknowledgement", {
- sequence: packet.sequence,
- sourceId: packet.channelSourceId,
- destId: packet.channelDestId,
- timeoutTimestamp: packet.timeoutTimestamp,
- data: packet.data,
- acknowledgement
+ // emit an acknowledgement event for each app acknowledgement in the acknowledgement
+ for i, ack in acknowledgment {
+ emitEvents("write_acknowledgement", {
+ sourceChannel: packet.sourceChannel,
+ destChannel: packet.destChannel,
+ sequence: packet.sequence, // value is string in decimal format
+ payloadSequence: i, // value is string in decimal format
+ acknowledgement: toHex(ack),
+ })
+ }
+
+ // Event Emission for receive packet. emit again so relayer can reconstruct the packet
+ emitEvents("recv_packet", {
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence, // value is string in decimal format
+ timeoutTimestamp: timeoutTimestamp, // value is string in decimal format
+ payloadLength: len(payloads), // value is string in decimal format
+ // include first payload data in events if there is only one payload
+ version: payload[0].version,
+ encoding: payload[0].encoding,
+ data: toHex(payload[0].appData) // emit app bytes as string in hex format
})
+
+ // for multi payload cases, we will emit each payload as a separate event
+ // these will include the packet identifier so they can be indexed and
+ // reconstructed by relayers
+ for i, payload in payloads {
+ emitEvents("recv_payload", {
+ sourceChannel: sourceChannelId,
+ destChannel: channel.counterpartyChannelId,
+ sequence: sequence, // value is string in decimal format
+ payloadSequence: i, // value is string in payload format
+ version: payload.version,
+ encoding: payload.encoding,
+ data: toHex(payload.appData) // emit app bytes as string in hex format
+ })
+ }
+
// delete the packet from state
storedPacket[destChannelId,sequence]=nil
}
@@ -814,9 +880,9 @@ Pre-conditions:
| **Condition Type** | **Description** | **Code Checks** |
|-------------------------------|---------------------------------|---------------------------------|
-| **Error-Conditions** | 1. `packetCommitment` already cleared out
2. Unset Acknowledgment
3. Unsuccessful payload execution.
4. Unexpected counterparty channel id | 1. `provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === null`
2. `verifyMembership(packetacknowledgementPath,...,) == False`
3. `onAcknowledgePacket(packet.channelSourceId,payload, acknowledgement) == False`
4. `packet.sourceChannelId != channel.counterpartyChannelId` |
-| **Post-Conditions (Success)** | 1. `onAcknowledgePacket` is executed and the application state is modified
2. `packetCommitment` has been cleared out
4. Event is Emission
| 1. `onAcknowledgePacket(..)==True; app.State(beforeAcknowledgePacket)!=app.State(afterAcknowledgePacket)`
2. `provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === null`,
4. Check Event is Emitted
|
-| **Post-Conditions (Error)** | 1. If `onAcknowledgePacket` fails the application state is unchanged
2. `packetCommitment` has not been cleared out
3. acknowledgement is stil in store
4. No Event Emission
| 1. `onAcknowledgePacket(..)==False; app.State(beforeAcknowledgePacket)==app.State(afterAcknowledgePacket)`
2. `provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === commitV2Packet(packet)` 3. `verifyMembership(packetAcknowledgementPath,...,) == True`
4. Check No Event is Emitted
|
+| **Error-Conditions** | 1. `packetCommitment` already cleared out
2. Unset Acknowledgment
3. Unsuccessful payload execution.
4. Unexpected counterparty channel id | 1. `provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === null`
2. `verifyMembership(packetacknowledgementPath,...,) == False`
3. `onAcknowledgePacket(packet.sourceChannel,payload, acknowledgement) == False`
4. `packet.sourceChannelId != channel.counterpartyChannelId` |
+| **Post-Conditions (Success)** | 1. `onAcknowledgePacket` is executed and the application state is modified
2. `packetCommitment` has been cleared out
4. Event is Emission
| 1. `onAcknowledgePacket(..)==True; app.State(beforeAcknowledgePacket)!=app.State(afterAcknowledgePacket)`
2. `provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === null`,
4. Check Event is Emitted
|
+| **Post-Conditions (Error)** | 1. If `onAcknowledgePacket` fails the application state is unchanged
2. `packetCommitment` has not been cleared out
3. acknowledgement is stil in store
4. No Event Emission
| 1. `onAcknowledgePacket(..)==False; app.State(beforeAcknowledgePacket)==app.State(afterAcknowledgePacket)`
2. `provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === commitV2Packet(packet)` 3. `verifyMembership(packetAcknowledgementPath,...,) == True`
4. Check No Event is Emitted
|
###### Pseudo-Code
@@ -834,7 +900,7 @@ function acknowledgePacket(
) {
// Channel and Client Checks
- channel = getChannel(packet.channelSourceId)
+ channel = getChannel(packet.sourceChannel)
assert(channel !== null)
client = router.clients[channel.clientId]
assert(client !== null)
@@ -843,10 +909,10 @@ function acknowledgePacket(
assert(packet.sourceChannelId == channel.counterpartyChannelId)
// verify we sent the packet and haven't cleared it out yet
- assert(provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === commitV2Packet(packet))
+ assert(provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === commitV2Packet(packet))
// verify that the acknowledgement exist at the desired path
- ackPath = packetAcknowledgementPath(packet.channelDestId, packet.sequence)
+ ackPath = packetAcknowledgementPath(packet.destChannel, packet.sequence)
merklePath = applyPrefix(channel.keyPrefix, ackPath)
assert(client.verifyMembership(
client.clientState
@@ -860,21 +926,23 @@ function acknowledgePacket(
// Executes Application logic ∀ Payload
payload=packet.data[0]
cbs = router.callbacks[payload.sourcePort]
- success= cbs.OnAcknowledgePacket(packet.channelSourceId,packet.channelDestId,packet.sequence,payload,acknowledgement, relayer) // Note that payload includes the version. The application is required to inspect the version to route the data to the proper callback
+ success= cbs.OnAcknowledgePacket(packet.sourceChannel,packet.destChannel,packet.sequence,payload,acknowledgement, relayer) // Note that payload includes the version. The application is required to inspect the version to route the data to the proper callback
abortUnless(success)
}
- channelStore.delete(packetCommitmentPath(packet.channelSourceId, packet.sequence))
+ channelStore.delete(packetCommitmentPath(packet.sourceChannel, packet.sequence))
+
+ // emit an acknowledgement event for each app acknowledgement in the acknowledgement
+ for i, ack in acknowledgment {
+ emitEvents("acknowledgePacket", {
+ sourceChannel: packet.sourceChannel,
+ destChannel: packet.destChannel,
+ sequence: packet.sequence, // value is string in decimal format
+ payloadSequence: i // value is string in decimal format
+ acknowledgement: toHex(ack),
+ })
+ }
- // Event Emission // Check fields
- emitLogEntry("acknowledgePacket", {
- sequence: packet.sequence,
- sourceId: packet.channelSourceId,
- destId: packet.channelDestId,
- timeoutTimestamp: packet.timeoutTimestamp,
- data: packet.data,
- acknowledgement
- })
}
```
@@ -929,9 +997,9 @@ Pre-conditions:
| **Condition Type** | **Description**| **Code Checks**|
|-------------------------------|--------------------|--------------------|
-| **Error-Conditions** | 1. `packetCommitment` already cleared out
2. `packetReceipt` is not empty
3. Unsuccessful payload execution
4. `timeoutTimestamp` not elapsed on the receiving chain
5. Unexpected counterparty channel id| 1. `provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === null`
2. `provableStore.get(packetReceiptPath(packet.channelDestId, packet.sequence))!=null`
3. `onTimeoutPacket(packet.channelSourceId,payload) == False`
4.1 `packet.timeoutTimestamp > 0`
4.2 `proofTimestamp = client.getTimestampAtHeight(proofHeight); proofTimestamp >= packet.timeoutTimestamp`
5. `packet.sourceChannelId != channel.counterpartyChannelId` |
-| **Post-Conditions (Success)** | 1. `onTimeoutPacket` is executed and the application state is modified
2. `packetCommitment` has been cleared out
3. `packetReceipt` is empty
4. Event is Emitted
| 1. `onTimeoutPacket(..)==True; app.State(beforeTimeoutPacket)!=app.State(afterTimeoutPacket)`
2. `provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === null`
3. `provableStore.get(packetReceiptPath(packet.channelDestId, packet.sequence))==null`
4. Check Event is Emitted
|
-| **Post-Conditions (Error)** | 1. If `onTimeoutPacket` fails and the application state is unchanged
2. `packetCommitment` is not cleared out
3. No Event Emission
| 1. `onTimeoutPacket(..)==False; app.State(beforeTimeoutPacket)==app.State(afterTimeoutPacket)`
2. `provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence)) === null`
3. Check No Event is Emitted
|
+| **Error-Conditions** | 1. `packetCommitment` already cleared out
2. `packetReceipt` is not empty
3. Unsuccessful payload execution
4. `timeoutTimestamp` not elapsed on the receiving chain
5. Unexpected counterparty channel id| 1. `provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === null`
2. `provableStore.get(packetReceiptPath(packet.destChannel, packet.sequence))!=null`
3. `onTimeoutPacket(packet.sourceChannel,payload) == False`
4.1 `packet.timeoutTimestamp > 0`
4.2 `proofTimestamp = client.getTimestampAtHeight(proofHeight); proofTimestamp >= packet.timeoutTimestamp`
5. `packet.sourceChannelId != channel.counterpartyChannelId` |
+| **Post-Conditions (Success)** | 1. `onTimeoutPacket` is executed and the application state is modified
2. `packetCommitment` has been cleared out
3. `packetReceipt` is empty
4. Event is Emitted
| 1. `onTimeoutPacket(..)==True; app.State(beforeTimeoutPacket)!=app.State(afterTimeoutPacket)`
2. `provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === null`
3. `provableStore.get(packetReceiptPath(packet.destChannel, packet.sequence))==null`
4. Check Event is Emitted
|
+| **Post-Conditions (Error)** | 1. If `onTimeoutPacket` fails and the application state is unchanged
2. `packetCommitment` is not cleared out
3. No Event Emission
| 1. `onTimeoutPacket(..)==False; app.State(beforeTimeoutPacket)==app.State(afterTimeoutPacket)`
2. `provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence)) === null`
3. Check No Event is Emitted
|
###### Pseudo-Code
@@ -947,7 +1015,7 @@ function timeoutPacket(
relayer: string
) {
// Channel and Client Checks
- channel = getChannel(packet.channelSourceId)
+ channel = getChannel(packet.sourceChannel)
assert(client !== null)
client = router.clients[channel.clientId]
@@ -957,7 +1025,7 @@ function timeoutPacket(
assert(packet.sourceChannelId == channel.counterpartyChannelId)
// verify we sent the packet and haven't cleared it out yet
- assert(provableStore.get(packetCommitmentPath(packet.channelSourceId, packet.sequence))
+ assert(provableStore.get(packetCommitmentPath(packet.sourceChannel, packet.sequence))
=== commitV2Packet(packet))
// get the timestamp from the final consensus state in the channel path
@@ -968,7 +1036,7 @@ function timeoutPacket(
assert(packet.timeoutTimestamp > 0 && proofTimestamp >= packet.timeoutTimestamp)
// verify there is no packet receipt --> receivePacket has not been called
- receiptPath = packetReceiptPath(packet.channelDestId, packet.sequence)
+ receiptPath = packetReceiptPath(packet.destChannel, packet.sequence)
merklePath = applyPrefix(channel.keyPrefix, receiptPath)
assert(client.verifyNonMembership(
client.clientState,
@@ -979,19 +1047,16 @@ function timeoutPacket(
payload=packet.data[0]
cbs = router.callbacks[payload.sourcePort]
- success=cbs.OnTimeoutPacket(packet.channelSourceId,packet.channelDestId,packet.sequence,payload,relayer) // Note that payload includes the version. The application is required to inspect the version to route the data to the proper callback
+ success=cbs.OnTimeoutPacket(packet.sourceChannel,packet.destChannel,packet.sequence,payload,relayer) // Note that payload includes the version. The application is required to inspect the version to route the data to the proper callback
abortUnless(success)
- channelStore.delete(packetCommitmentPath(packet.channelSourceId, packet.sequence))
+ channelStore.delete(packetCommitmentPath(packet.sourceChannel, packet.sequence))
- // Event Emission // See fields
- emitLogEntry("timeoutPacket", {
- sequence: packet.sequence,
- sourceId: packet.channelSourceId,
- destId: packet.channelDestId,
- timeoutTimestamp: packet.timeoutTimestamp,
- data: packet.data,
- acknowledgement
+ // Event Emission for timeout packet
+ emitEvents("timeoutPacket", {
+ sequence: packet.sequence, // value is string in decimal format
+ sourceChannel: packet.sourceChannel,
+ destChannel: packet.destChannel,
})
}
```