Skip to content

Commit ac561b4

Browse files
authored
fix: allow zero proof height, solo machine discards provided proof height in favor of sequence (#2746)
imp: allow proof height to be zero for all core IBC `sdk.Msg` types that contain proofs. imp: discard proofHeight for solo machines and use the solo machine sequence instead.
1 parent fe5fb15 commit ac561b4

File tree

12 files changed

+501
-140
lines changed

12 files changed

+501
-140
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
7676

7777
### Improvements
7878

79+
* (core) [\#2746](https://github.com/cosmos/ibc-go/pull/2746) Allow proof height to be zero for all core IBC `sdk.Msg` types that contain proofs.
80+
* (light-clients/06-solomachine) [\#2746](https://github.com/cosmos/ibc-go/pull/2746) Discard proofHeight for solo machines and use the solo machine sequence instead.
7981
* (modules/light-clients/07-tendermint) [\#1713](https://github.com/cosmos/ibc-go/pull/1713) Allow client upgrade proposals to update `TrustingPeriod`. See ADR-026 for context.
8082
* (modules/core/02-client) [\#1188](https://github.com/cosmos/ibc-go/pull/1188/files) Routing `MsgSubmitMisbehaviour` to `UpdateClient` keeper function. Deprecating `SubmitMisbehaviour` endpoint.
8183
* (modules/core/02-client) [\#1208](https://github.com/cosmos/ibc-go/pull/1208) Replace `CheckHeaderAndUpdateState` usage in 02-client with calls to `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour` and `UpdateState`.

docs/migrations/v6-to-v7.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ The `CheckMisbehaviourAndUpdateState` function has been removed from `ClientStat
4545

4646
The function `GetTimestampAtHeight` has been added to the `ClientState` interface. It should return the timestamp for a consensus state associated with the provided height.
4747

48+
A zero proof height is now allowed by core IBC and may be passed into `VerifyMembership` and `VerifyNonMembership`. Light clients are responsible for returning an error if a zero proof height is invalid behaviour.
49+
4850
### `Header` and `Misbehaviour`
4951

5052
`exported.Header` and `exported.Misbehaviour` interface types have been merged and renamed to `ClientMessage` interface.

modules/core/03-connection/types/msgs.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,6 @@ func (msg MsgConnectionOpenTry) ValidateBasic() error {
139139
if len(msg.ProofConsensus) == 0 {
140140
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of consensus state")
141141
}
142-
if msg.ProofHeight.IsZero() {
143-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
144-
}
145142
if msg.ConsensusHeight.IsZero() {
146143
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "consensus height must be non-zero")
147144
}
@@ -226,9 +223,6 @@ func (msg MsgConnectionOpenAck) ValidateBasic() error {
226223
if len(msg.ProofConsensus) == 0 {
227224
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of consensus state")
228225
}
229-
if msg.ProofHeight.IsZero() {
230-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
231-
}
232226
if msg.ConsensusHeight.IsZero() {
233227
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "consensus height must be non-zero")
234228
}
@@ -271,9 +265,6 @@ func (msg MsgConnectionOpenConfirm) ValidateBasic() error {
271265
if len(msg.ProofAck) == 0 {
272266
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof ack")
273267
}
274-
if msg.ProofHeight.IsZero() {
275-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
276-
}
277268
_, err := sdk.AccAddressFromBech32(msg.Signer)
278269
if err != nil {
279270
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)

modules/core/03-connection/types/msgs_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() {
144144
{"empty proofInit", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false},
145145
{"empty proofClient", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, signer), false},
146146
{"empty proofConsensus", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, signer), false},
147-
{"invalid proofHeight", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, signer), false},
148147
{"invalid consensusHeight", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), signer), false},
149148
{"empty singer", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ""), false},
150149
{"success", types.NewMsgConnectionOpenTry("clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), true},
@@ -191,7 +190,6 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() {
191190
{"empty proofTry", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false},
192191
{"empty proofClient", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false},
193192
{"empty proofConsensus", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false},
194-
{"invalid proofHeight", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, ibctesting.ConnectionVersion, signer), false},
195193
{"invalid consensusHeight", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), ibctesting.ConnectionVersion, signer), false},
196194
{"invalid version", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, &types.Version{}, signer), false},
197195
{"empty signer", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, ""), false},
@@ -212,7 +210,6 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenConfirm() {
212210
testMsgs := []*types.MsgConnectionOpenConfirm{
213211
types.NewMsgConnectionOpenConfirm("test/conn1", suite.proof, clientHeight, signer),
214212
types.NewMsgConnectionOpenConfirm(connectionID, emptyProof, clientHeight, signer),
215-
types.NewMsgConnectionOpenConfirm(connectionID, suite.proof, clienttypes.ZeroHeight(), signer),
216213
types.NewMsgConnectionOpenConfirm(connectionID, suite.proof, clientHeight, ""),
217214
types.NewMsgConnectionOpenConfirm(connectionID, suite.proof, clientHeight, signer),
218215
}
@@ -224,9 +221,8 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenConfirm() {
224221
}{
225222
{testMsgs[0], false, "invalid connection ID"},
226223
{testMsgs[1], false, "empty proofTry"},
227-
{testMsgs[2], false, "invalid proofHeight"},
228-
{testMsgs[3], false, "empty signer"},
229-
{testMsgs[4], true, "success"},
224+
{testMsgs[2], false, "empty signer"},
225+
{testMsgs[3], true, "success"},
230226
}
231227

232228
for i, tc := range testCases {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ func (suite *KeeperTestSuite) TestChanCloseInit() {
640640
path.SetChannelOrdered()
641641
err = path.EndpointA.ChanOpenInit()
642642
suite.Require().NoError(err)
643-
643+
644644
// ensure channel capability check passes
645645
suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
646646
channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)

modules/core/04-channel/types/msgs.go

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ func (msg MsgChannelOpenTry) ValidateBasic() error {
9595
if len(msg.ProofInit) == 0 {
9696
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof init")
9797
}
98-
if msg.ProofHeight.IsZero() {
99-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
100-
}
10198
if msg.Channel.State != TRYOPEN {
10299
return sdkerrors.Wrapf(ErrInvalidChannelState,
103100
"channel state must be TRYOPEN in MsgChannelOpenTry. expected: %s, got: %s",
@@ -159,9 +156,6 @@ func (msg MsgChannelOpenAck) ValidateBasic() error {
159156
if len(msg.ProofTry) == 0 {
160157
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof try")
161158
}
162-
if msg.ProofHeight.IsZero() {
163-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
164-
}
165159
_, err := sdk.AccAddressFromBech32(msg.Signer)
166160
if err != nil {
167161
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
@@ -207,9 +201,6 @@ func (msg MsgChannelOpenConfirm) ValidateBasic() error {
207201
if len(msg.ProofAck) == 0 {
208202
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof ack")
209203
}
210-
if msg.ProofHeight.IsZero() {
211-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
212-
}
213204
_, err := sdk.AccAddressFromBech32(msg.Signer)
214205
if err != nil {
215206
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
@@ -294,9 +285,6 @@ func (msg MsgChannelCloseConfirm) ValidateBasic() error {
294285
if len(msg.ProofInit) == 0 {
295286
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof init")
296287
}
297-
if msg.ProofHeight.IsZero() {
298-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
299-
}
300288
_, err := sdk.AccAddressFromBech32(msg.Signer)
301289
if err != nil {
302290
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
@@ -335,9 +323,6 @@ func (msg MsgRecvPacket) ValidateBasic() error {
335323
if len(msg.ProofCommitment) == 0 {
336324
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof")
337325
}
338-
if msg.ProofHeight.IsZero() {
339-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
340-
}
341326
_, err := sdk.AccAddressFromBech32(msg.Signer)
342327
if err != nil {
343328
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
@@ -384,9 +369,6 @@ func (msg MsgTimeout) ValidateBasic() error {
384369
if len(msg.ProofUnreceived) == 0 {
385370
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty unreceived proof")
386371
}
387-
if msg.ProofHeight.IsZero() {
388-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
389-
}
390372
if msg.NextSequenceRecv == 0 {
391373
return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "next sequence receive cannot be 0")
392374
}
@@ -435,9 +417,6 @@ func (msg MsgTimeoutOnClose) ValidateBasic() error {
435417
if len(msg.ProofClose) == 0 {
436418
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of closed counterparty channel end")
437419
}
438-
if msg.ProofHeight.IsZero() {
439-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
440-
}
441420
_, err := sdk.AccAddressFromBech32(msg.Signer)
442421
if err != nil {
443422
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
@@ -479,9 +458,6 @@ func (msg MsgAcknowledgement) ValidateBasic() error {
479458
if len(msg.ProofAcked) == 0 {
480459
return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof")
481460
}
482-
if msg.ProofHeight.IsZero() {
483-
return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero")
484-
}
485461
if len(msg.Acknowledgement) == 0 {
486462
return sdkerrors.Wrap(ErrInvalidAcknowledgement, "ack bytes cannot be empty")
487463
}

modules/core/04-channel/types/msgs_test.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
clienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
1717
"github.com/cosmos/ibc-go/v6/modules/core/04-channel/types"
1818
commitmenttypes "github.com/cosmos/ibc-go/v6/modules/core/23-commitment/types"
19-
"github.com/cosmos/ibc-go/v6/modules/core/exported"
2019
"github.com/cosmos/ibc-go/v6/testing/simapp"
2120
)
2221

@@ -56,9 +55,7 @@ var (
5655
packet = types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp)
5756
invalidPacket = types.NewPacket(unknownPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp)
5857

59-
emptyProof = []byte{}
60-
invalidProofs1 = exported.Proof(nil)
61-
invalidProofs2 = emptyProof
58+
emptyProof = []byte{}
6259

6360
addr = sdk.AccAddress("testaddr111111111111").String()
6461
emptyAddr string
@@ -158,7 +155,6 @@ func (suite *TypesTestSuite) TestMsgChannelOpenTryValidateBasic() {
158155
{"too long port id", types.NewMsgChannelOpenTry(invalidLongPort, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false},
159156
{"port id contains non-alpha", types.NewMsgChannelOpenTry(invalidPort, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false},
160157
{"", types.NewMsgChannelOpenTry(portid, version, types.ORDERED, connHops, cpportid, cpchanid, "", suite.proof, height, addr), true},
161-
{"proof height is zero", types.NewMsgChannelOpenTry(portid, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, clienttypes.ZeroHeight(), addr), false},
162158
{"invalid channel order", types.NewMsgChannelOpenTry(portid, version, types.Order(4), connHops, cpportid, cpchanid, version, suite.proof, height, addr), false},
163159
{"connection hops more than 1 ", types.NewMsgChannelOpenTry(portid, version, types.UNORDERED, invalidConnHops, cpportid, cpchanid, version, suite.proof, height, addr), false},
164160
{"too short connection id", types.NewMsgChannelOpenTry(portid, version, types.UNORDERED, invalidShortConnHops, cpportid, cpchanid, version, suite.proof, height, addr), false},
@@ -202,7 +198,6 @@ func (suite *TypesTestSuite) TestMsgChannelOpenAckValidateBasic() {
202198
{"channel id contains non-alpha", types.NewMsgChannelOpenAck(portid, invalidChannel, chanid, version, suite.proof, height, addr), false},
203199
{"", types.NewMsgChannelOpenAck(portid, chanid, chanid, "", suite.proof, height, addr), true},
204200
{"empty proof", types.NewMsgChannelOpenAck(portid, chanid, chanid, version, emptyProof, height, addr), false},
205-
{"proof height is zero", types.NewMsgChannelOpenAck(portid, chanid, chanid, version, suite.proof, clienttypes.ZeroHeight(), addr), false},
206201
{"invalid counterparty channel id", types.NewMsgChannelOpenAck(portid, chanid, invalidShortChannel, version, suite.proof, height, addr), false},
207202
}
208203

@@ -235,7 +230,6 @@ func (suite *TypesTestSuite) TestMsgChannelOpenConfirmValidateBasic() {
235230
{"too long channel id", types.NewMsgChannelOpenConfirm(portid, invalidLongChannel, suite.proof, height, addr), false},
236231
{"channel id contains non-alpha", types.NewMsgChannelOpenConfirm(portid, invalidChannel, suite.proof, height, addr), false},
237232
{"empty proof", types.NewMsgChannelOpenConfirm(portid, chanid, emptyProof, height, addr), false},
238-
{"proof height is zero", types.NewMsgChannelOpenConfirm(portid, chanid, suite.proof, clienttypes.ZeroHeight(), addr), false},
239233
}
240234

241235
for _, tc := range testCases {
@@ -297,7 +291,6 @@ func (suite *TypesTestSuite) TestMsgChannelCloseConfirmValidateBasic() {
297291
{"too long channel id", types.NewMsgChannelCloseConfirm(portid, invalidLongChannel, suite.proof, height, addr), false},
298292
{"channel id contains non-alpha", types.NewMsgChannelCloseConfirm(portid, invalidChannel, suite.proof, height, addr), false},
299293
{"empty proof", types.NewMsgChannelCloseConfirm(portid, chanid, emptyProof, height, addr), false},
300-
{"proof height is zero", types.NewMsgChannelCloseConfirm(portid, chanid, suite.proof, clienttypes.ZeroHeight(), addr), false},
301294
}
302295

303296
for _, tc := range testCases {
@@ -322,7 +315,6 @@ func (suite *TypesTestSuite) TestMsgRecvPacketValidateBasic() {
322315
expPass bool
323316
}{
324317
{"success", types.NewMsgRecvPacket(packet, suite.proof, height, addr), true},
325-
{"proof height is zero", types.NewMsgRecvPacket(packet, suite.proof, clienttypes.ZeroHeight(), addr), false},
326318
{"proof contain empty proof", types.NewMsgRecvPacket(packet, emptyProof, height, addr), false},
327319
{"missing signer address", types.NewMsgRecvPacket(packet, suite.proof, height, emptyAddr), false},
328320
{"invalid packet", types.NewMsgRecvPacket(invalidPacket, suite.proof, height, addr), false},
@@ -358,7 +350,6 @@ func (suite *TypesTestSuite) TestMsgTimeoutValidateBasic() {
358350
expPass bool
359351
}{
360352
{"success", types.NewMsgTimeout(packet, 1, suite.proof, height, addr), true},
361-
{"proof height must be > 0", types.NewMsgTimeout(packet, 1, suite.proof, clienttypes.ZeroHeight(), addr), false},
362353
{"seq 0", types.NewMsgTimeout(packet, 0, suite.proof, height, addr), false},
363354
{"missing signer address", types.NewMsgTimeout(packet, 1, suite.proof, height, emptyAddr), false},
364355
{"cannot submit an empty proof", types.NewMsgTimeout(packet, 1, emptyProof, height, addr), false},
@@ -390,7 +381,6 @@ func (suite *TypesTestSuite) TestMsgTimeoutOnCloseValidateBasic() {
390381
{"seq 0", types.NewMsgTimeoutOnClose(packet, 0, suite.proof, suite.proof, height, addr), false},
391382
{"empty proof", types.NewMsgTimeoutOnClose(packet, 1, emptyProof, suite.proof, height, addr), false},
392383
{"empty proof close", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, emptyProof, height, addr), false},
393-
{"proof height is zero", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, clienttypes.ZeroHeight(), addr), false},
394384
{"signer address is empty", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, height, emptyAddr), false},
395385
{"invalid packet", types.NewMsgTimeoutOnClose(invalidPacket, 1, suite.proof, suite.proof, height, addr), false},
396386
}
@@ -417,7 +407,6 @@ func (suite *TypesTestSuite) TestMsgAcknowledgementValidateBasic() {
417407
expPass bool
418408
}{
419409
{"success", types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, height, addr), true},
420-
{"proof height must be > 0", types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, clienttypes.ZeroHeight(), addr), false},
421410
{"empty ack", types.NewMsgAcknowledgement(packet, nil, suite.proof, height, addr), false},
422411
{"missing signer address", types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, height, emptyAddr), false},
423412
{"cannot submit an empty proof", types.NewMsgAcknowledgement(packet, packet.GetData(), emptyProof, height, addr), false},

0 commit comments

Comments
 (0)