Skip to content

Commit d4daf80

Browse files
committed
Add a section on encoding IBCReceive errors
1 parent 0f19bc0 commit d4daf80

File tree

1 file changed

+63
-5
lines changed

1 file changed

+63
-5
lines changed

IBC.md

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,9 @@ pub fn ibc_packet_receive(
261261

262262
Note the different return response here (`IbcReceiveResponse` rather than
263263
`IbcBasicResponse`)? This is because it has an extra field
264-
`acknowledgement: Binary`, which must be filled out. That is the response bytes
265-
that will be returned to the original contract, informing it of failure or
266-
success. (Note: this is vague as it will be refined in the next PR)
264+
`acknowledgement: Binary`, which must be filled out. All successful message must
265+
return an encoded `Acknowledgement` response in this field, that can be parsed
266+
by the sending chain (see below for the standard format).
267267

268268
Here is the
269269
[`IbcPacket` structure](https://github.com/CosmWasm/cosmwasm/blob/v0.14.0-beta4/packages/std/src/ibc.rs#L129-L146)
@@ -299,8 +299,66 @@ pub struct IbcPacket {
299299
}
300300
```
301301

302-
TODO: explain how to handle/parse errors (As part of
303-
https://github.com/CosmWasm/cosmwasm/issues/762)
302+
##### Error Handling
303+
304+
A major issue that is unique to `ibc_packet_receive` is that it is expected to
305+
often reject an incoming packet, but it cannot abort the transaction. We
306+
actually expect all state changes from the contract (as well as dispatched
307+
messages) to be reverted when the packet is rejected, but the transaction to
308+
properly commit an acknowledgement with encoded error (to be read by the sending
309+
chain).
310+
311+
The atomicity issue was first
312+
[analyzed in the Cosmos SDK implementation](https://github.com/cosmos/ibc-go/issues/68)
313+
and refined into
314+
[changing semantics of the OnRecvPacket SDK method](https://github.com/cosmos/ibc-go/issues/91),
315+
which was
316+
[implemented in April 2021](https://github.com/cosmos/ibc-go/pull/107), likely
317+
to be released with Cosmos SDK 0.43 or 0.44. Since we want the best,
318+
future-proof interface for contracts, we will use an approach inspired by that
319+
work, and add an adapter in `wasmd` until we can upgrade to a Cosmos SDK version
320+
that implements this.
321+
322+
The contract will need to correctly create a success `Acknowledgement` in the
323+
`Response`, before any messages are dispatched. However, if any of the
324+
dispatched messages (or the contract itself) returns and error, the runtime will
325+
revert all state changes caused by running this (including in messages and
326+
submessages) and return an error acknowledgement rather than the original
327+
success that may have been returned.
328+
329+
There was quite some
330+
[discussion on how to encode the errors](https://github.com/CosmWasm/cosmwasm/issues/762),
331+
but in the end, I propose a simple default implementation with an easy opt-in
332+
for custom messages. If the contract or any messages return an error, we end up
333+
with a simple error string, which is not designed for IBC Packets. The default
334+
behavior will be to take that string and embed it into a JSON-encoded "Standard
335+
Acknowledgement Format", as defined below. This will work for ICS20 and is
336+
recommended to be used for all CosmWasm designed protocols.
337+
338+
To enable compatibility with other protocols, a contract can expose an optional
339+
export to "rewrite" the error into the proper format. This would look like:
340+
341+
```rust
342+
#[entry_point]
343+
pub fn ibc_encode_receive_error(
344+
deps: Deps,
345+
env: Env,
346+
packet: IbcPacket,
347+
error: String,
348+
) -> StdResult<Binary> { }
349+
```
350+
351+
The function receives the original packet as well as the error string returned,
352+
and is responsible for creating a proper binary-encoded "error acknowledgement"
353+
that can be sent to the calling contract. For example, it could protobuf-encode
354+
the `Acknowledgement message` defined below. `Deps`, `Env` and `IbcPacket` are
355+
passed just in case more context is needed for encoding, but likely unused. This
356+
function should never return an error (even if the IbcPacket was malformed), but
357+
we allow it to return one if there is some pathological state (rather than
358+
panicking in the contract,`StdResult::Err` returns useful information to the
359+
caller). If this returns an error, the transaction will return an error, meaning
360+
no acknowledgement nor receipt will be writen, and then same packet may be
361+
relayer again later.
304362

305363
##### Standard Acknowledgement Format
306364

0 commit comments

Comments
 (0)