Skip to content

Commit 69b259a

Browse files
committed
Add a section on encoding IBCReceive errors
1 parent f0c3d6b commit 69b259a

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
@@ -267,9 +267,9 @@ pub fn ibc_packet_receive(
267267

268268
Note 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

274274
Here 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

Comments
 (0)