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