Skip to content

Commit

Permalink
disable defensive timestamp check for solo machines in SendPacket (#214)
Browse files Browse the repository at this point in the history
* disable defensive timestamp check for solo machines

* add changelog
  • Loading branch information
colin-axner authored Jun 9, 2021
1 parent 7a44bf7 commit 605a865
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug Fixes

* (06-solomachine) [\#214](https://github.com/cosmos/ibc-go/pull/214) Disable defensive timestamp check in SendPacket for solo machine clients.
* (07-tendermint) [#\210](https://github.com/cosmos/ibc-go/pull/210) Export all consensus metadata on genesis restarts for tendermint clients.
* (core) [\#200](https://github.com/cosmos/ibc-go/pull/200) Fixes incorrect export of IBC identifier sequences. Previously, the next identifier sequence for clients/connections/channels was not set during genesis export. This resulted in the next identifiers being generated on the new chain to reuse old identifiers (the sequences began again from 0).
* (02-client) [\#192](https://github.com/cosmos/ibc-go/pull/192) Fix IBC `query ibc client header` cli command. Support historical queries for query header/node-state commands.
Expand Down
23 changes: 16 additions & 7 deletions modules/core/04-channel/keeper/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (k Keeper) SendPacket(
return sdkerrors.Wrapf(clienttypes.ErrClientNotActive, "cannot send packet using client (%s) with status %s", connectionEnd.GetClientID(), status)
}

// check if packet timeouted on the receiving chain
// check if packet is timed out on the receiving chain
latestHeight := clientState.GetLatestHeight()
timeoutHeight := packet.GetTimeoutHeight()
if !timeoutHeight.IsZero() && latestHeight.GTE(timeoutHeight) {
Expand All @@ -84,16 +84,25 @@ func (k Keeper) SendPacket(
)
}

latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight)
clientType, _, err := clienttypes.ParseClientIdentifier(connectionEnd.GetClientID())
if err != nil {
return err
}

if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() {
return sdkerrors.Wrapf(
types.ErrPacketTimeout,
"receiving chain block timestamp >= packet timeout timestamp (%s >= %s)", time.Unix(0, int64(latestTimestamp)), time.Unix(0, int64(packet.GetTimeoutTimestamp())),
)
// NOTE: this is a temporary fix. Solo machine does not support usage of 'GetTimestampAtHeight'
// A future change should move this function to be a ClientState callback.
if clientType != exported.Solomachine {
latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight)
if err != nil {
return err
}

if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() {
return sdkerrors.Wrapf(
types.ErrPacketTimeout,
"receiving chain block timestamp >= packet timeout timestamp (%s >= %s)", time.Unix(0, int64(latestTimestamp)), time.Unix(0, int64(packet.GetTimeoutTimestamp())),
)
}
}

nextSequenceSend, found := k.GetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel())
Expand Down
27 changes: 27 additions & 0 deletions modules/core/04-channel/keeper/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ func (suite *KeeperTestSuite) TestSendPacket() {
packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
}, true},
{"success with solomachine: UNORDERED channel", func() {
suite.coordinator.Setup(path)
// swap client with solo machine
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinesingle", "testing", 1)
path.EndpointA.ClientID = clienttypes.FormatClientIdentifier(exported.Solomachine, 10)
path.EndpointA.SetClientState(solomachine.ClientState())
connection := path.EndpointA.GetConnection()
connection.ClientId = path.EndpointA.ClientID
path.EndpointA.SetConnection(connection)

packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
}, true},
{"success with solomachine: ORDERED channel", func() {
path.SetChannelOrdered()
suite.coordinator.Setup(path)
// swap client with solomachine
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinesingle", "testing", 1)
path.EndpointA.ClientID = clienttypes.FormatClientIdentifier(exported.Solomachine, 10)
path.EndpointA.SetClientState(solomachine.ClientState())
connection := path.EndpointA.GetConnection()
connection.ClientId = path.EndpointA.ClientID
path.EndpointA.SetConnection(connection)

packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
}, true},
{"sending packet out of order on UNORDERED channel", func() {
// setup creates an unordered channel
suite.coordinator.Setup(path)
Expand Down

0 comments on commit 605a865

Please sign in to comment.