-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Give contracts finer control on IBC packet acknowledgement #1721
Comments
This is an interesting idea. Thanks for bringing this up! |
Note: with the current impl in wasmd, the submessages returned with IbcReceiveResponse may create response data that "overwrite" the nil ack. |
A single contract can do it, just like the single ibc-transfer module can maintain channels with multiple chains. |
Yep, Polytone and my project (ICS-999) already uses this trick. However, the ack is always written during the execution of the MsgRecvPacket. What packet-forward-middleware does, is to not write an ack for packet1 at all. It instead dispatches another packet (packet2) to the destination chain (Juno in my example). When Juno sends the ack for packet2 back to Noble, the middleware finally writes the ack for packet1. |
How does this trick work? This may help shape an API. How is it possible to write a "the nil ack"? What is a nil ack? An ack with empty bytes? |
In ibc-go's porttypes.Middleware interface, the This is the behavior that PFM utilizes: https://github.com/strangelove-ventures/packet-forward-middleware/blob/v6.0.2/router/ibc_middleware.go#L225-L227
The trick is this: at the end of the the pub fn packet_receive(
deps: DepsMut,
env: Env,
packet: IbcPacket,
) -> Result<IbcReceiveResponse, ContractError> {
// ...
// we don't do set_ack on the IbcReceiveResponse here,
// so the ack is empty bytes by default.
Ok(IbcReceiveResponse::new()
.add_submessage(SubMsg::reply_always(
// ...
)))
} Why? Because we don't know the content of the ack yet. We need to execute the submessage first, and based on the result of the submessage determine what to put in the ack. In the reply of that submessage, we set data in the response: Ok(Response::new().set_data(
// ...
)) The wasm module will interpret this Tbh, I think this is a somewhat confusing behavior. Here's a similar opinion found on twitter: https://twitter.com/0xArt3miX/status/1667968274410225673 I think it'd be much clearer to
|
Thank you! Moved this over to cosmwasm as suggested by Alex. Here we can change the contract APIs and then integrate. Independent of the current override behaviour it makes sense to make writing the ack optional and allow writing the acknowledgement separately. When we are doing that it should be possible to write the ack in a different block, which means some security considerations must be done to avoid writing someone else's ack.
I don't think we should make this the default. In the majority of cases you want to write an ack. #1649 goes in the opposite direction and makes setting it required so you don't forget. But |
@webmaster128 Edited my response above with a better explanation
Edited, I no longer suggest removing it, but rather make it an |
This makes sense, like it |
🤝 Will do some more checks with Alex and especially look into the long polling use case. But overall this sounds solid. |
In ICS-004: Writing acknowledgements you find additional background around async achnowledgements, which is what is requested here. |
In the first release of CosmWasm 2.0, we make writing the ack optional as this is the breaking change (#1892). This does not yet allow you to write it later. The API for writing it later will be created later on. Removing this from the 2.0 milestone to reflect this breakdown. |
This feature would be a big help! |
What's the use case? |
We have a cosmwasm implementation acting as a bridge between ICS20 and a Solidity contract (generalization of ICS20 allowing multi-denom transfer and custom encoding for packets to be efficient on EVM). It's 99% compatible with ICS20, PFM being the only exception here, as described by @larry0x. Hence, the |
If this feature is important to you, please have a look into #2130 to ensure we are not missing something. Thanks! |
I'm attempting to implement something similar to the packet-forward-middleware as a CosmWasm contract. Unfortunately, as a Go module, PFM is able to control how to write acknowledgement for a packet in a way not available to CW contracts.
How PFM works
Consider a transfer of USDC following the route Osmosis → Noble → Juno. Let's call Osmosis → Noble
packet1
and Noble → Junopacket2
.On Osmosis, the sender includes a JSON in
packet1
's memo field, instructing that the tokens are to be forwarded to Juno.On Noble, on receiving
packet1
, the middleware generates another ICS-20 packet (packet2
) and send it to Juno. When it does this, it does NOT write an ack forpacket1
just yet. It returnsnil
at the end of theOnRecvPacket
function so that no ack is written: https://github.com/strangelove-ventures/packet-forward-middleware/blob/v6.0.2/router/ibc_middleware.go#L225-L227Once the middleware receives an ack for
packet2
from Juno, it finally writes an ack forpacket1
: https://github.com/strangelove-ventures/packet-forward-middleware/blob/v6.0.2/router/ibc_middleware.go#L263It does so by directly calling the ics4Wrapper's
WriteAcknowledgement
method: https://github.com/strangelove-ventures/packet-forward-middleware/blob/v6.0.2/router/keeper/keeper.go#L184-L193Why this is not possible for CW contracts
When a packet is delivered to a CW contract, the wasm module always writes an ack. This is the case even when the contract does not add a
data
to theIbcReceiveResponse
: https://github.com/CosmWasm/wasmd/blob/v0.31.0/x/wasm/ibc.go#L282There isn't a way for contracts to directly invoke
ics4Wrapper.WriteAcknowledgement
as the Go module can.My suggestion
Make the
data
field inIbcReceiveResponse
optional:and only write an ack if the data is
Some
.Add a new
IbcMsg::WriteAcknowledgement
binding which invokesics4Wrapper.WriteAcknowledgement
.These would allow contracts to completely replicate the behavior of packet-forward-middleware.
The text was updated successfully, but these errors were encountered: