Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* [\#8545](https://github.com/cosmos/ibc-go/pull/8545) Support sending multiple payloads in the same packet for atomic payload execution.

### Dependencies

* [\#8369](https://github.com/cosmos/ibc-go/pull/8369) Bump **github.com/CosmWasm/wasmvm** to **2.2.4**
Expand Down
310 changes: 310 additions & 0 deletions modules/apps/transfer/v2/transfer_test.go

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions modules/core/04-channel/v2/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@

var isAsync bool
isSuccess := true
// Cache context before doing any application callbacks
// so that we may write or discard state changes from callbacks atomically.
cacheCtx, writeFn = ctx.CacheContext()
for _, pd := range msg.Packet.Payloads {
// Cache context so that we may discard state changes from callback if the acknowledgement is unsuccessful.
cacheCtx, writeFn = ctx.CacheContext()
cb := k.Router.Route(pd.DestinationPort)
res := cb.OnRecvPacket(cacheCtx, msg.Packet.SourceClient, msg.Packet.DestinationClient, msg.Packet.Sequence, pd, signer)

Expand All @@ -96,8 +97,6 @@
if bytes.Equal(res.GetAcknowledgement(), types.ErrorAcknowledgement[:]) {
return nil, errorsmod.Wrapf(types.ErrInvalidAcknowledgement, "application acknowledgement cannot be sentinel error acknowledgement")
}
// write application state changes for asynchronous and successful acknowledgements
writeFn()
// append app acknowledgement to the overall acknowledgement
ack.AppAcknowledgements = append(ack.AppAcknowledgements, res.Acknowledgement)
} else {
Expand All @@ -122,18 +121,19 @@
}
}

// write application state changes for asynchronous and successful acknowledgements
// if any application returns a failure, then we discard all state changes
// to ensure an atomic execution of all payloads
if isSuccess {
writeFn()
}

if !isAsync {
// If the application callback was successful, the acknowledgement must have the same number of app acknowledgements as the packet payloads.
if isSuccess {
if len(ack.AppAcknowledgements) != len(msg.Packet.Payloads) {
return nil, errorsmod.Wrapf(types.ErrInvalidAcknowledgement, "length of app acknowledgement %d does not match length of app payload %d", len(ack.AppAcknowledgements), len(msg.Packet.Payloads))
}
// sanity check to ensure returned acknowledgement and calculated isSuccess boolean matches
if ack.Success() != isSuccess {
panic("acknowledgement success does not match isSuccess")

Check warning on line 134 in modules/core/04-channel/v2/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

modules/core/04-channel/v2/keeper/msg_server.go#L134

Added line #L134 was not covered by tests
}

// Validate ack before forwarding to WriteAcknowledgement.
if err := ack.Validate(); err != nil {
return nil, err
}
// Set packet acknowledgement only if the acknowledgement is not async.
// NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the
// acknowledgement is async.
Expand Down
Loading
Loading