-
Notifications
You must be signed in to change notification settings - Fork 596
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
Add FlushStatus Checks to RecvPacket #3914
Changes from 7 commits
a290fed
adfc53e
31acbec
6a36bc5
40d9351
b182061
79be234
20da85f
b590bed
fb983cc
f8ac337
4f4ecf9
cbdc846
9396ea4
4edd3b9
5ded370
b8dce46
6f09439
aee4623
f047c40
919fa83
f146dc3
3849847
fa273eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -33,7 +33,14 @@ func (k Keeper) SendPacket( | |||||
return 0, errorsmod.Wrap(types.ErrChannelNotFound, sourceChannel) | ||||||
} | ||||||
|
||||||
if channel.State != types.OPEN { | ||||||
if channel.FlushStatus != types.NOTINFLUSH { | ||||||
return 0, errorsmod.Wrapf( | ||||||
types.ErrInvalidChannelState, | ||||||
"channel should not be in %s state", types.NOTINFLUSH.String(), | ||||||
) | ||||||
} | ||||||
|
||||||
if channel.State != types.OPEN || channel.FlushStatus != types.NOTINFLUSH { | ||||||
return 0, errorsmod.Wrapf( | ||||||
types.ErrInvalidChannelState, | ||||||
"channel is not OPEN (got %s)", channel.State.String(), | ||||||
|
@@ -129,7 +136,8 @@ func (k Keeper) RecvPacket( | |||||
return errorsmod.Wrap(types.ErrChannelNotFound, packet.GetDestChannel()) | ||||||
} | ||||||
|
||||||
if channel.State != types.OPEN { | ||||||
counterpartyLastPacketSent, _ := k.GetCounterpartyLastPacketSequence(ctx, packet.GetDestPort(), packet.GetDestChannel()) | ||||||
if channel.State != types.OPEN && (channel.FlushStatus != types.FLUSHING || counterpartyLastPacketSent > packet.GetSequence()) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it easier to reason about like this:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we typically go with the approach of negating the spec conditions right? I do agree with you though that this makes it easier to reason (and, as a result, implement) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree with @crodriguezvega it's easier to reason about this way, made a small adjustment to the code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we actually add a condition in the code that if the channel is CLOSED then we can't recv packets? kinda weird if we can receive packets then right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we shouldn't be able to. If state is CLOSED, flush status should be NOTINFLUSH and the condition should resolve to true (but see this comment #3914 (comment), I don't think its currently defined when a close can occur) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh! didnt see that comment, thanks! yea. that makes sense. |
||||||
return errorsmod.Wrapf( | ||||||
types.ErrInvalidChannelState, | ||||||
"channel state is not OPEN (got %s)", channel.State.String(), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message should be updated as well, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let me know what you think of the updated message |
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -217,6 +217,30 @@ func (suite *KeeperTestSuite) TestSendPacket() { | |
|
||
channelCap = capabilitytypes.NewCapability(5) | ||
}, false}, | ||
{ | ||
"invalid flush status: FLUSHING", | ||
func() { | ||
suite.coordinator.Setup(path) | ||
sourceChannel = path.EndpointA.ChannelID | ||
|
||
channel := path.EndpointA.GetChannel() | ||
channel.FlushStatus = types.FLUSHING | ||
path.EndpointA.SetChannel(channel) | ||
}, | ||
false, | ||
}, | ||
{ | ||
"invalid flush status: FLUSHCOMPLETE", | ||
func() { | ||
suite.coordinator.Setup(path) | ||
sourceChannel = path.EndpointA.ChannelID | ||
|
||
channel := path.EndpointA.GetChannel() | ||
channel.FlushStatus = types.FLUSHCOMPLETE | ||
path.EndpointA.SetChannel(channel) | ||
}, | ||
false, | ||
}, | ||
} | ||
|
||
for i, tc := range testCases { | ||
|
@@ -294,6 +318,58 @@ 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}, | ||
{ | ||
msg: "success with closed channel: FLUSHING status", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, maybe the condition in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it currently is possible to be in such a state if a message to close the channel is submitted during the upgrade handshake? Even if I'm missing something and that isn't possible we should definitely amend the channel closing handlers to set the flushing status to NOTINFLUSH. |
||
malleate: 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) | ||
|
||
channel := path.EndpointB.GetChannel() | ||
channel.State = types.CLOSED | ||
channel.FlushStatus = types.FLUSHING | ||
path.EndpointB.SetChannel(channel) | ||
}, | ||
expPass: true, | ||
}, | ||
{ | ||
msg: "failure with closed channel counterparty sequence > packet sequence", | ||
malleate: 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) | ||
|
||
channel := path.EndpointB.GetChannel() | ||
channel.State = types.CLOSED | ||
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) | ||
}, | ||
expPass: false, | ||
}, | ||
{ | ||
msg: "failure with closed channel not flushing", | ||
malleate: 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) | ||
|
||
channel := path.EndpointB.GetChannel() | ||
channel.State = types.CLOSED | ||
channel.FlushStatus = types.FLUSHCOMPLETE | ||
path.EndpointB.SetChannel(channel) | ||
|
||
suite.chainB.GetSimApp().IBCKeeper.ChannelKeeper.SetCounterpartyLastPacketSequence(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence) | ||
}, | ||
expPass: false, | ||
}, | ||
{"packet already relayed ORDERED channel (no-op)", func() { | ||
expError = types.ErrNoOpMsg | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following is duplicated below on L50?
This check is also included in the expression on L43?
We can do both checks and use
||
but the error info would need to include both channel state and flush status. Or we can do both checks one after another which I'd be happy enough with too.fwiw I think its an invalid/unreachable state to have
state == OPEN
andflushStatus != NOTINFLUSH
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, this check is duplicated, I think this is due to branching off the SendPacket branch before this was fixed. I think we can remove all changes to
SendPacket
in this PR.