Skip to content

Commit 81b35aa

Browse files
authored
Merge pull request #3 from rootulp/rp/channel-keeper-json
fix(core/04-channel): check JSON deserialization is deterministic
2 parents a934597 + a46592b commit 81b35aa

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

modules/core/04-channel/keeper/packet.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,15 @@ func (k Keeper) AcknowledgePacket(
436436

437437
packetCommitment := types.CommitPacket(k.cdc, packet)
438438

439+
var ack types.Acknowledgement
440+
err := types.SubModuleCdc.UnmarshalJSON(acknowledgement, &ack)
441+
if err == nil {
442+
ackBz := ack.Acknowledgement()
443+
if !bytes.Equal(ackBz, acknowledgement) {
444+
return sdkerrors.Wrap(types.ErrInvalidAcknowledgement, "acknowledgement marshalling error")
445+
}
446+
}
447+
439448
// verify we sent the packet and haven't cleared it out yet
440449
if !bytes.Equal(commitment, packetCommitment) {
441450
return sdkerrors.Wrapf(types.ErrInvalidPacket, "commitment bytes are not equal: got (%v), expected (%v)", packetCommitment, commitment)

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

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
588588
var (
589589
path *ibctesting.Path
590590
packet types.Packet
591-
ack = ibcmock.MockAcknowledgement
591+
ack []byte
592592

593593
channelCap *capabilitytypes.Capability
594594
expError *sdkerrors.Error
@@ -642,7 +642,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
642642

643643
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
644644

645-
err = path.EndpointA.AcknowledgePacket(packet, ack.Acknowledgement())
645+
err = path.EndpointA.AcknowledgePacket(packet, ack)
646646
suite.Require().NoError(err)
647647
}, false},
648648
{"packet already acknowledged unordered channel (no-op)", func() {
@@ -662,7 +662,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
662662

663663
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
664664

665-
err = path.EndpointA.AcknowledgePacket(packet, ack.Acknowledgement())
665+
err = path.EndpointA.AcknowledgePacket(packet, ack)
666666
suite.Require().NoError(err)
667667
}, false},
668668
{"channel not found", func() {
@@ -804,7 +804,7 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
804804
suite.chainA.App.GetIBCKeeper().ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, packet.GetSequence(), types.CommitPacket(suite.chainA.App.AppCodec(), packet))
805805

806806
// manually set packet acknowledgement and capability
807-
suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, packet.GetSequence(), types.CommitAcknowledgement(ack.Acknowledgement()))
807+
suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, packet.GetSequence(), types.CommitAcknowledgement(ack))
808808

809809
suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
810810
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
@@ -832,21 +832,74 @@ func (suite *KeeperTestSuite) TestAcknowledgePacket() {
832832
suite.chainA.App.GetIBCKeeper().ChannelKeeper.SetNextSequenceAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 10)
833833
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
834834
}, false},
835+
{
836+
"fake acknowledgement",
837+
func() {
838+
expError = types.ErrInvalidAcknowledgement
839+
// setup uses an UNORDERED channel
840+
suite.coordinator.Setup(path)
841+
842+
// create packet commitment
843+
sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
844+
suite.Require().NoError(err)
845+
846+
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
847+
848+
// write packet acknowledgement directly
849+
// Create a valid acknowledgement using deterministic serialization.
850+
ack = types.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement()
851+
// Introduce non-determinism: insert an extra space after the first character '{'
852+
// This will deserialize correctly but fail to re-serialize to the expected bytes.
853+
if len(ack) > 0 && ack[0] == '{' {
854+
ack = []byte("{ " + string(ack[1:]))
855+
}
856+
path.EndpointB.Chain.Coordinator.UpdateTimeForChain(path.EndpointB.Chain)
857+
858+
path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(path.EndpointB.Chain.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence, types.CommitAcknowledgement(ack))
859+
860+
path.EndpointB.Chain.NextBlock()
861+
path.EndpointA.UpdateClient()
862+
},
863+
false,
864+
},
865+
{
866+
"non-standard acknowledgement", func() {
867+
// setup uses an UNORDERED channel
868+
suite.coordinator.Setup(path)
869+
870+
// create packet commitment
871+
sequence, err := path.EndpointA.SendPacket(defaultTimeoutHeight, disabledTimeoutTimestamp, ibctesting.MockPacketData)
872+
suite.Require().NoError(err)
873+
874+
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
875+
876+
// write packet acknowledgement directly
877+
ack = []byte(`{"somethingelse":"anything"}`)
878+
path.EndpointB.Chain.Coordinator.UpdateTimeForChain(path.EndpointB.Chain)
879+
880+
path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(path.EndpointB.Chain.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sequence, types.CommitAcknowledgement(ack))
881+
882+
path.EndpointB.Chain.NextBlock()
883+
path.EndpointA.UpdateClient()
884+
},
885+
true,
886+
},
835887
}
836888

837889
for i, tc := range testCases {
838890
tc := tc
839891
suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
840892
suite.SetupTest() // reset
841893
expError = nil // must explcitly set error for failed cases
894+
ack = ibcmock.MockAcknowledgement.Acknowledgement()
842895
path = ibctesting.NewPath(suite.chainA, suite.chainB)
843896

844897
tc.malleate()
845898

846899
packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
847900
proof, proofHeight := path.EndpointB.QueryProof(packetKey)
848901

849-
err := suite.chainA.App.GetIBCKeeper().ChannelKeeper.AcknowledgePacket(suite.chainA.GetContext(), channelCap, packet, ack.Acknowledgement(), proof, proofHeight)
902+
err := suite.chainA.App.GetIBCKeeper().ChannelKeeper.AcknowledgePacket(suite.chainA.GetContext(), channelCap, packet, ack, proof, proofHeight)
850903
pc := suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
851904

852905
channelA, _ := suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetChannel(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel())

0 commit comments

Comments
 (0)