@@ -261,9 +261,9 @@ pub fn ibc_packet_receive(
261261
262262Note 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
268268Here 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