Skip to content

Commit

Permalink
feat: Add defensive replay protection check into WriteAcknowledgement (
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangdv2429 authored Feb 27, 2024
1 parent e361c28 commit 829d06f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
10 changes: 10 additions & 0 deletions modules/core/04-channel/keeper/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,16 @@ func (k Keeper) WriteAcknowledgement(
)
}

// REPLAY PROTECTION: The recvStartSequence will prevent historical proofs from allowing replay
// attacks on packets processed in previous lifecycles of a channel. After a successful channel
// upgrade all packets under the recvStartSequence will have been processed and thus should be
// rejected. Any asynchronous acknowledgement writes from packets processed in a previous lifecycle of a channel
// will also be rejected.
recvStartSequence, _ := k.GetRecvStartSequence(ctx, packet.GetDestPort(), packet.GetDestChannel())
if packet.GetSequence() < recvStartSequence {
return errorsmod.Wrap(types.ErrPacketReceived, "packet already processed in previous channel upgrade")
}

// NOTE: IBC app modules might have written the acknowledgement synchronously on
// the OnRecvPacket callback so we need to check if the acknowledgement is already
// set on the store and return an error if so.
Expand Down
16 changes: 16 additions & 0 deletions modules/core/04-channel/keeper/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,22 @@ func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
},
false,
},
{
"packet already received",
func() {
path.Setup()

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)
ack = ibcmock.MockAcknowledgement

// set recv seq start to indicate packet was processed in previous upgrade
suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetRecvStartSequence(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence+1)
},
false,
},
}
for i, tc := range testCases {
tc := tc
Expand Down

0 comments on commit 829d06f

Please sign in to comment.