diff --git a/CHANGELOG.md b/CHANGELOG.md index acfcf52334e..8e7ff94dc07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (testing) [\#810](https://github.com/cosmos/ibc-go/pull/810) Additional testing function added to `Endpoint` type called `RecvPacketWithResult`. Performs the same functionality as the existing `RecvPacket` function but also returns the message result. `path.RelayPacket` no longer uses the provided acknowledgement argument and instead obtains the acknowledgement via MsgRecvPacket events. * (connection) [\#721](https://github.com/cosmos/ibc-go/pull/721) Simplify connection handshake error messages when unpacking client state. * (channel) [\#692](https://github.com/cosmos/ibc-go/pull/692) Minimize channel logging by only emitting the packet sequence, source port/channel, destination port/channel upon packet receives, acknowledgements and timeouts. * [\#383](https://github.com/cosmos/ibc-go/pull/383) Adds helper functions for merging and splitting middleware versions from the underlying app version. diff --git a/testing/endpoint.go b/testing/endpoint.go index 4c3804879c9..39fe2b4408c 100644 --- a/testing/endpoint.go +++ b/testing/endpoint.go @@ -3,7 +3,7 @@ package ibctesting import ( "fmt" - // sdk "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" @@ -375,6 +375,17 @@ func (endpoint *Endpoint) SendPacket(packet exported.PacketI) error { // RecvPacket receives a packet on the associated endpoint. // The counterparty client is updated. func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { + _, err := endpoint.RecvPacketWithResult(packet) + if err != nil { + return err + } + + return nil +} + +// RecvPacketWithResult receives a packet on the associated endpoint and the result +// of the transaction is returned. The counterparty client is updated. +func (endpoint *Endpoint) RecvPacketWithResult(packet channeltypes.Packet) (*sdk.Result, error) { // get proof of packet commitment on source packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey) @@ -382,11 +393,16 @@ func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) // receive on counterparty and update source client - if err := endpoint.Chain.sendMsgs(recvMsg); err != nil { - return err + res, err := endpoint.Chain.SendMsgs(recvMsg) + if err != nil { + return nil, err } - return endpoint.Counterparty.UpdateClient() + if err := endpoint.Counterparty.UpdateClient(); err != nil { + return nil, err + } + + return res, nil } // WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint. diff --git a/testing/events.go b/testing/events.go index 9666a82ffca..037a4c342e3 100644 --- a/testing/events.go +++ b/testing/events.go @@ -55,3 +55,18 @@ func ParseChannelIDFromEvents(events sdk.Events) (string, error) { } return "", fmt.Errorf("channel identifier event attribute not found") } + +// ParseAckFromEvents parses events emitted from a MsgRecvPacket and returns the +// acknowledgement. +func ParseAckFromEvents(events sdk.Events) ([]byte, error) { + for _, ev := range events { + if ev.Type == channeltypes.EventTypeWriteAck { + for _, attr := range ev.Attributes { + if string(attr.Key) == channeltypes.AttributeKeyAck { + return attr.Value, nil + } + } + } + } + return nil, fmt.Errorf("acknowledgement event attribute not found") +} diff --git a/testing/path.go b/testing/path.go index d90bc5e1171..f60faeaa051 100644 --- a/testing/path.go +++ b/testing/path.go @@ -38,14 +38,20 @@ func (path *Path) SetChannelOrdered() { // RelayPacket attempts to relay the packet first on EndpointA and then on EndpointB // if EndpointA does not contain a packet commitment for that packet. An error is returned // if a relay step fails or the packet commitment does not exist on either endpoint. -func (path *Path) RelayPacket(packet channeltypes.Packet, ack []byte) error { +func (path *Path) RelayPacket(packet channeltypes.Packet, _ []byte) error { pc := path.EndpointA.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointA.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointA.Chain.App.AppCodec(), packet)) { // packet found, relay from A to B path.EndpointB.UpdateClient() - if err := path.EndpointB.RecvPacket(packet); err != nil { + res, err := path.EndpointB.RecvPacketWithResult(packet) + if err != nil { + return err + } + + ack, err := ParseAckFromEvents(res.GetEvents()) + if err != nil { return err } @@ -62,9 +68,16 @@ func (path *Path) RelayPacket(packet channeltypes.Packet, ack []byte) error { // packet found, relay B to A path.EndpointA.UpdateClient() - if err := path.EndpointA.RecvPacket(packet); err != nil { + res, err := path.EndpointA.RecvPacketWithResult(packet) + if err != nil { return err } + + ack, err := ParseAckFromEvents(res.GetEvents()) + if err != nil { + return err + } + if err := path.EndpointB.AcknowledgePacket(packet, ack); err != nil { return err }