Skip to content

Commit

Permalink
Amend recvPacket as per spec. (#4386)
Browse files Browse the repository at this point in the history
* Amend recvPacket as per spec.

* Update modules/core/04-channel/keeper/packet_test.go

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

* Drop usage of CounterpartyLastSequenceSend.

* Cover all cases.

* Use SetChannelCounterpartyUpgrade.

* Add expected errors, remove duplicate test.

* Remove setting of counterparty last sequence send in other test case.

* Shorthand initialization of dummy upgrade.

* Apply suggestions from code review

Co-authored-by: Damian Nolan <damiannolan@gmail.com>

---------

Co-authored-by: Damian Nolan <damiannolan@gmail.com>
Co-authored-by: Cian Hatton <cian@interchain.io>
  • Loading branch information
3 people authored Aug 24, 2023
1 parent 7302d9b commit 9372c6c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 47 deletions.
22 changes: 15 additions & 7 deletions modules/core/04-channel/keeper/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,23 @@ func (k Keeper) RecvPacket(
return errorsmod.Wrap(types.ErrChannelNotFound, packet.GetDestChannel())
}

if !collections.Contains(channel.State, []types.State{types.OPEN, types.TRYUPGRADE, types.ACKUPGRADE}) {
return errorsmod.Wrapf(types.ErrInvalidChannelState, "expected channel state to be one of [%s, %s, %s], but got %s", types.OPEN.String(), types.TRYUPGRADE.String(), types.ACKUPGRADE.String(), channel.State.String())
if !collections.Contains(channel.State, []types.State{types.OPEN, types.STATE_FLUSHING}) {
return errorsmod.Wrapf(types.ErrInvalidChannelState, "expected channel state to be one of [%s, %s], but got %s", types.OPEN, types.STATE_FLUSHING, channel.State)
}

// in the case of the channel being in TRYUPGRADE or ACKUPGRADE we need to ensure that the channel is not in flushing,
// and that the counterparty last sequence send is less than or equal to the packet sequence.
if counterpartyLastSequenceSend, found := k.GetCounterpartyLastPacketSequence(ctx, packet.GetDestPort(), packet.GetDestChannel()); found {
if channel.FlushStatus != types.FLUSHING || packet.GetSequence() > counterpartyLastSequenceSend {
return errorsmod.Wrapf(types.ErrInvalidFlushStatus, "expected channel flush status to be (%s) when counterparty last sequence send (%d) is set, failed to recv packet (%d)", types.FLUSHING, counterpartyLastSequenceSend, packet.GetSequence())
// in the case of the channel being in FLUSHING we need to ensure that the the counterparty last sequence send
// is less than or equal to the packet sequence.
if channel.State == types.STATE_FLUSHING {
counterpartyUpgrade, found := k.GetCounterpartyUpgrade(ctx, packet.GetDestPort(), packet.GetDestChannel())
if !found {
return errorsmod.Wrapf(types.ErrUpgradeNotFound, "counterparty upgrade not found for channel: %s", packet.GetDestChannel())
}

if packet.GetSequence() > counterpartyUpgrade.LatestSequenceSend {
return errorsmod.Wrapf(
types.ErrInvalidPacket,
"failed to receive packet, cannot flush packet at sequence greater than counterparty last sequence send (%d) > (%d)", packet.GetSequence(), counterpartyUpgrade.LatestSequenceSend,
)
}
}

Expand Down
73 changes: 33 additions & 40 deletions modules/core/04-channel/keeper/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,37 +323,8 @@ func (suite *KeeperTestSuite) TestRecvPacket() {
// attempts to receive packet 2 without receiving packet 1
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
}, true},
// {
// "success with channel in ACKUPGRADE: FLUSHING status",
// func() {
// suite.coordinator.Setup(path)
// sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
// suite.Require().NoError(err)
// packet = types.NewPacket(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp)
// channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)

// // Move channel to correct state.
// path.EndpointB.ChannelConfig.ProposedUpgrade.Fields.Version = ibcmock.UpgradeVersion

// err = path.EndpointB.ChanUpgradeInit()
// suite.Require().NoError(err)

// err = path.EndpointA.ChanUpgradeTry()
// suite.Require().NoError(err)

// err = path.EndpointB.ChanUpgradeAck()
// suite.Require().NoError(err)

// channel := path.EndpointB.GetChannel()
// channel.FlushStatus = types.FLUSHING
// path.EndpointB.SetChannel(channel)

// suite.chainB.GetSimApp().IBCKeeper.ChannelKeeper.SetCounterpartyLastPacketSequence(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence+1)
// },
// true,
// },
{
"failure while upgrading channel, packet sequence > counterparty last send sequence",
"success with channel in flushing state",
func() {
suite.coordinator.Setup(path)
sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
Expand All @@ -362,45 +333,67 @@ func (suite *KeeperTestSuite) TestRecvPacket() {
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)

channel := path.EndpointB.GetChannel()
channel.State = types.INITUPGRADE
channel.FlushStatus = types.FLUSHING
channel.State = types.STATE_FLUSHING
path.EndpointB.SetChannel(channel)

suite.chainB.GetSimApp().IBCKeeper.ChannelKeeper.SetCounterpartyLastPacketSequence(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence-1)
// set last packet sent sequence to sequence + 1
counterpartyUpgrade := types.Upgrade{LatestSequenceSend: sequence + 1}
path.EndpointB.SetChannelCounterpartyUpgrade(counterpartyUpgrade)
},
true,
},
{
"failure while upgrading channel, counterparty upgrade not found",
func() {
expError = types.ErrUpgradeNotFound

suite.coordinator.Setup(path)
sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
suite.Require().NoError(err)
packet = types.NewPacket(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp)
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)

channel := path.EndpointB.GetChannel()
channel.State = types.STATE_FLUSHING
path.EndpointB.SetChannel(channel)
},
false,
},
{
"failure while upgrading channel, channel not flushing, packet sequence == counterparty last send sequence",
"failure while upgrading channel, packet sequence > counterparty last send sequence",
func() {
expError = types.ErrInvalidPacket

suite.coordinator.Setup(path)
sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
suite.Require().NoError(err)
packet = types.NewPacket(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp)
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)

channel := path.EndpointB.GetChannel()
channel.FlushStatus = types.FLUSHCOMPLETE
channel.State = types.STATE_FLUSHING
path.EndpointB.SetChannel(channel)

suite.chainB.GetSimApp().IBCKeeper.ChannelKeeper.SetCounterpartyLastPacketSequence(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence)
// set last packet sent sequence to sequence - 1
counterpartyUpgrade := types.Upgrade{LatestSequenceSend: sequence - 1}
path.EndpointB.SetChannelCounterpartyUpgrade(counterpartyUpgrade)
},
false,
},
{
"failure while upgrading channel, channel flushing, packet sequence > counterparty last send sequence",
"failure while upgrading channel, channel in flush complete state",
func() {
expError = types.ErrInvalidChannelState

suite.coordinator.Setup(path)
sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
suite.Require().NoError(err)
packet = types.NewPacket(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp)
channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)

channel := path.EndpointB.GetChannel()
channel.FlushStatus = types.FLUSHING
channel.State = types.STATE_FLUSHCOMPLETE
path.EndpointB.SetChannel(channel)

suite.chainB.GetSimApp().IBCKeeper.ChannelKeeper.SetCounterpartyLastPacketSequence(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence-1)
},
false,
},
Expand Down

0 comments on commit 9372c6c

Please sign in to comment.