refactor connection verify_test (#6588)
* refactor verify consensus state * refactor connection verification * simplify code, channel + packet commitment tests * refactor verify ack * refactor verify ack absence * refactor next seq recv test Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Christopher Goes <cwgoes@pluranimity.org>
This commit is contained in:
parent
fd9cdb8ba7
commit
bbe245ac1d
|
@ -42,6 +42,12 @@ const (
|
||||||
maxClockDrift time.Duration = time.Second * 10
|
maxClockDrift time.Duration = time.Second * 10
|
||||||
|
|
||||||
nextTimestamp = 10 // increment used for the next header's timestamp
|
nextTimestamp = 10 // increment used for the next header's timestamp
|
||||||
|
|
||||||
|
testPort1 = "firstport"
|
||||||
|
testPort2 = "secondport"
|
||||||
|
|
||||||
|
testChannel1 = "firstchannel"
|
||||||
|
testChannel2 = "secondchannel"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -2,424 +2,419 @@ package keeper_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
"github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
|
||||||
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
|
||||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
|
||||||
|
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// TestVerifyClientConsensusState verifies that the consensus state of
|
||||||
testPort1 = "firstport"
|
// chainA stored on clientB (which is on chainB) matches the consensus
|
||||||
testPort2 = "secondport"
|
// state for chainA at that height.
|
||||||
|
|
||||||
testChannel1 = "firstchannel"
|
|
||||||
testChannel2 = "secondchannel"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
|
func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
|
||||||
// create connection on chainA to chainB
|
var (
|
||||||
counterparty := types.NewCounterparty(
|
connA *ibctesting.TestConnection
|
||||||
testClientIDA, testConnectionIDA,
|
connB *ibctesting.TestConnection
|
||||||
commitmenttypes.NewMerklePrefix(suite.oldchainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix().Bytes()),
|
changeClientID bool
|
||||||
|
heightDiff uint64
|
||||||
)
|
)
|
||||||
connection1 := types.NewConnectionEnd(
|
|
||||||
types.UNINITIALIZED, testConnectionIDB, testClientIDB, counterparty,
|
|
||||||
types.GetCompatibleVersions(),
|
|
||||||
)
|
|
||||||
|
|
||||||
cases := []struct {
|
|
||||||
msg string
|
|
||||||
connection types.ConnectionEnd
|
|
||||||
malleate func() clientexported.ConsensusState
|
|
||||||
expPass bool
|
|
||||||
}{
|
|
||||||
{"verification success", connection1, func() clientexported.ConsensusState {
|
|
||||||
suite.oldchainA.CreateClient(suite.oldchainB)
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
consState := suite.oldchainA.Header.ConsensusState()
|
|
||||||
return consState
|
|
||||||
}, true},
|
|
||||||
{"client state not found", connection1, func() clientexported.ConsensusState {
|
|
||||||
return suite.oldchainB.Header.ConsensusState()
|
|
||||||
}, false},
|
|
||||||
{"verification failed", connection1, func() clientexported.ConsensusState {
|
|
||||||
suite.oldchainA.CreateClient(suite.oldchainA)
|
|
||||||
return suite.oldchainA.Header.ConsensusState()
|
|
||||||
}, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Client of chain B on Chain App
|
|
||||||
// Check that we can verify B's consensus state on chain A
|
|
||||||
for i, tc := range cases {
|
|
||||||
tc := tc
|
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
|
||||||
suite.SetupTest() // reset
|
|
||||||
|
|
||||||
consState := tc.malleate()
|
|
||||||
|
|
||||||
// perform a couple updates of chain B on chain A
|
|
||||||
suite.oldchainA.updateClient(suite.oldchainB)
|
|
||||||
suite.oldchainA.updateClient(suite.oldchainB)
|
|
||||||
|
|
||||||
// TODO: is this the right consensus height
|
|
||||||
consensusHeight := suite.oldchainA.Header.GetHeight()
|
|
||||||
consensusKey := prefixedClientKey(testClientIDA, host.KeyConsensusState(consensusHeight))
|
|
||||||
|
|
||||||
// get proof that chainB stored chainA' consensus state
|
|
||||||
proof, proofHeight := queryProof(suite.oldchainB, consensusKey)
|
|
||||||
|
|
||||||
err := suite.oldchainA.App.IBCKeeper.ConnectionKeeper.VerifyClientConsensusState(
|
|
||||||
suite.oldchainA.GetContext(), tc.connection, proofHeight+1, consensusHeight, proof, consState,
|
|
||||||
)
|
|
||||||
|
|
||||||
if tc.expPass {
|
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
|
||||||
} else {
|
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestVerifyConnectionState() {
|
|
||||||
connectionKey := host.KeyConnection(testConnectionIDA)
|
|
||||||
var invalidProofHeight uint64
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg string
|
msg string
|
||||||
malleate func()
|
malleate func()
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{"verification success", func() {
|
{"verification success", func() {
|
||||||
suite.oldchainA.CreateClient(suite.oldchainB)
|
_, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
invalidProofHeight = 0 // don't use this
|
|
||||||
}, true},
|
}, true},
|
||||||
{"client state not found", func() {}, false},
|
{"client state not found", func() {
|
||||||
|
_, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||||
|
|
||||||
|
changeClientID = true
|
||||||
|
}, false},
|
||||||
|
{"consensus state not found", func() {
|
||||||
|
_, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||||
|
|
||||||
|
heightDiff = 5
|
||||||
|
}, false},
|
||||||
{"verification failed", func() {
|
{"verification failed", func() {
|
||||||
suite.oldchainA.CreateClient(suite.oldchainB)
|
_, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
clientB := connB.ClientID
|
||||||
invalidProofHeight = 10 // make proofHeight incorrect
|
|
||||||
|
// give chainB wrong consensus state for chainA
|
||||||
|
consState, found := suite.chainB.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), clientB)
|
||||||
|
suite.Require().True(found)
|
||||||
|
|
||||||
|
tmConsState, ok := consState.(ibctmtypes.ConsensusState)
|
||||||
|
suite.Require().True(ok)
|
||||||
|
|
||||||
|
tmConsState.Timestamp = time.Now()
|
||||||
|
suite.chainB.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainB.GetContext(), clientB, tmConsState.Height, tmConsState)
|
||||||
|
|
||||||
|
suite.coordinator.CommitBlock(suite.chainB)
|
||||||
}, false},
|
}, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chains A and B create clients for each other
|
for _, tc := range cases {
|
||||||
// A creates connectionEnd for chain B and stores it in state
|
|
||||||
// Check that B can verify connection is stored after some updates
|
|
||||||
for i, tc := range cases {
|
|
||||||
tc := tc
|
tc := tc
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
suite.Run(tc.msg, func() {
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
heightDiff = 0 // must be explicitly changed in malleate
|
||||||
|
changeClientID = false // must be explicitly changed in malleate
|
||||||
|
|
||||||
tc.malleate()
|
tc.malleate()
|
||||||
|
|
||||||
// create and store connection on chain A
|
connection := suite.chainA.GetConnection(connA)
|
||||||
expectedConnection := suite.oldchainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDB, testClientIDA, types.OPEN)
|
if changeClientID {
|
||||||
|
connection.ClientID = ibctesting.InvalidID
|
||||||
// // create expected connection
|
|
||||||
// TODO: why is this commented
|
|
||||||
// expectedConnection := types.NewConnectionEnd(types.INIT, testClientIDB, counterparty, []string{"1.0.0"})
|
|
||||||
|
|
||||||
// perform a couple updates of chain A on chain B
|
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
|
||||||
proof, proofHeight := queryProof(suite.oldchainA, connectionKey)
|
|
||||||
// if invalidProofHeight has been set, use that value instead
|
|
||||||
if invalidProofHeight != 0 {
|
|
||||||
proofHeight = invalidProofHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create B's connection to A
|
proof, consensusHeight := suite.chainB.QueryConsensusStateProof(connB.ClientID)
|
||||||
counterparty := types.NewCounterparty(testClientIDB, testConnectionIDB, commitmenttypes.NewMerklePrefix([]byte("ibc")))
|
proofHeight := uint64(suite.chainA.GetContext().BlockHeight() - 1)
|
||||||
connection := types.NewConnectionEnd(types.UNINITIALIZED, testConnectionIDA, testClientIDA, counterparty, []string{"1.0.0"})
|
consensusState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetSelfConsensusState(suite.chainA.GetContext(), consensusHeight)
|
||||||
// Ensure chain B can verify connection exists in chain A
|
suite.Require().True(found)
|
||||||
err := suite.oldchainB.App.IBCKeeper.ConnectionKeeper.VerifyConnectionState(
|
|
||||||
suite.oldchainB.GetContext(), connection, proofHeight+1, proof, testConnectionIDA, expectedConnection,
|
err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyClientConsensusState(
|
||||||
|
suite.chainA.GetContext(), connection,
|
||||||
|
proofHeight+heightDiff, consensusHeight, proof, consensusState,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestVerifyConnectionState verifies the connection state of the connection
|
||||||
|
// on chainB. The connections on chainA and chainB are fully opened.
|
||||||
|
func (suite *KeeperTestSuite) TestVerifyConnectionState() {
|
||||||
|
cases := []struct {
|
||||||
|
msg string
|
||||||
|
changeClientID bool
|
||||||
|
changeConnectionState bool
|
||||||
|
heightDiff uint64
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{"verification success", false, false, 0, true},
|
||||||
|
{"client state not found - changed client ID", true, false, 0, false},
|
||||||
|
{"consensus state not found - increased proof height", false, false, 5, false},
|
||||||
|
{"verification failed - connection state is different than proof", false, true, 0, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
tc := tc
|
||||||
|
|
||||||
|
suite.Run(tc.msg, func() {
|
||||||
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
|
_, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
|
||||||
|
|
||||||
|
connection := suite.chainA.GetConnection(connA)
|
||||||
|
if tc.changeClientID {
|
||||||
|
connection.ClientID = ibctesting.InvalidID
|
||||||
|
}
|
||||||
|
expectedConnection := suite.chainB.GetConnection(connB)
|
||||||
|
|
||||||
|
connectionKey := host.KeyConnection(connB.ID)
|
||||||
|
proof, proofHeight := suite.chainB.QueryProof(connectionKey)
|
||||||
|
|
||||||
|
if tc.changeConnectionState {
|
||||||
|
expectedConnection.State = types.TRYOPEN
|
||||||
|
}
|
||||||
|
|
||||||
|
err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyConnectionState(
|
||||||
|
suite.chainA.GetContext(), connection,
|
||||||
|
proofHeight+tc.heightDiff, proof, connB.ID, expectedConnection,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestVerifyChannelState verifies the channel state of the channel on
|
||||||
|
// chainB. The channels on chainA and chainB are fully opened.
|
||||||
func (suite *KeeperTestSuite) TestVerifyChannelState() {
|
func (suite *KeeperTestSuite) TestVerifyChannelState() {
|
||||||
channelKey := host.KeyChannel(testPort1, testChannel1)
|
|
||||||
|
|
||||||
// create connection of chainB to pass into verify function
|
|
||||||
counterparty := types.NewCounterparty(
|
|
||||||
testClientIDB, testConnectionIDB,
|
|
||||||
commitmenttypes.NewMerklePrefix(suite.oldchainA.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix().Bytes()),
|
|
||||||
)
|
|
||||||
|
|
||||||
connection := types.NewConnectionEnd(
|
|
||||||
types.UNINITIALIZED, testConnectionIDA, testClientIDA, counterparty,
|
|
||||||
types.GetCompatibleVersions(),
|
|
||||||
)
|
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg string
|
msg string
|
||||||
proofHeight uint64
|
changeClientID bool
|
||||||
malleate func()
|
changeChannelState bool
|
||||||
|
heightDiff uint64
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{"verification success", 0, func() {
|
{"verification success", false, false, 0, true},
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
{"client state not found- changed client ID", true, false, 0, false},
|
||||||
}, true},
|
{"consensus state not found - increased proof height", false, false, 5, false},
|
||||||
{"client state not found", 0, func() {}, false},
|
{"verification failed - changed channel state", false, true, 0, false},
|
||||||
{"consensus state not found", 100, func() {
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
}, false},
|
|
||||||
{"verification failed", 7, func() {
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainB)
|
|
||||||
}, false},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chain A creates channel for chain B and stores in its state
|
for _, tc := range cases {
|
||||||
// Check that chainB can verify channel is stored in chain A
|
|
||||||
for i, tc := range cases {
|
|
||||||
tc := tc
|
tc := tc
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
tc.malleate()
|
_, _, connA, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
// Create and store channel on chain A
|
connection := suite.chainA.GetConnection(connA)
|
||||||
channel := suite.oldchainA.createChannel(
|
if tc.changeClientID {
|
||||||
testPort1, testChannel1, testPort2, testChannel2,
|
connection.ClientID = ibctesting.InvalidID
|
||||||
channeltypes.OPEN, channeltypes.ORDERED, testConnectionIDA,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update chainA client on chainB
|
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
|
||||||
|
|
||||||
// Check that Chain B can verify channel is stored on chainA
|
|
||||||
proof, proofHeight := queryProof(suite.oldchainA, channelKey)
|
|
||||||
// if testcase proofHeight is not 0, replace proofHeight with this value
|
|
||||||
if tc.proofHeight != 0 {
|
|
||||||
proofHeight = tc.proofHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := suite.oldchainB.App.IBCKeeper.ConnectionKeeper.VerifyChannelState(
|
channelKey := host.KeyChannel(channelB.PortID, channelB.ID)
|
||||||
suite.oldchainB.GetContext(), connection, proofHeight+1, proof, testPort1,
|
proof, proofHeight := suite.chainB.QueryProof(channelKey)
|
||||||
testChannel1, channel,
|
|
||||||
|
channel := suite.chainB.GetChannel(channelB)
|
||||||
|
if tc.changeChannelState {
|
||||||
|
channel.State = channeltypes.TRYOPEN
|
||||||
|
}
|
||||||
|
|
||||||
|
err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyChannelState(
|
||||||
|
suite.chainA.GetContext(), connection, proofHeight+tc.heightDiff, proof,
|
||||||
|
channelB.PortID, channelB.ID, channel,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestVerifyPacketCommitmentState has chainB verify the packet commitment
|
||||||
|
// on channelA. The channels on chainA and chainB are fully opened and a
|
||||||
|
// packet is sent from chainA to chainB, but has not been received.
|
||||||
func (suite *KeeperTestSuite) TestVerifyPacketCommitment() {
|
func (suite *KeeperTestSuite) TestVerifyPacketCommitment() {
|
||||||
commitmentKey := host.KeyPacketCommitment(testPort1, testChannel1, 1)
|
|
||||||
commitmentBz := []byte("commitment")
|
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg string
|
msg string
|
||||||
proofHeight uint64
|
changeClientID bool
|
||||||
malleate func()
|
changePacketCommitmentState bool
|
||||||
|
heightDiff uint64
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{"verification success", 0, func() {
|
{"verification success", false, false, 0, true},
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
{"client state not found- changed client ID", true, false, 0, false},
|
||||||
}, true},
|
{"consensus state not found - increased proof height", false, false, 5, false},
|
||||||
{"client state not found", 0, func() {}, false},
|
{"verification failed - changed packet commitment state", false, true, 0, false},
|
||||||
{"consensus state not found", 100, func() {
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
}, false},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainA sets packet commitment on channel with chainB in its state
|
for _, tc := range cases {
|
||||||
// Check that ChainB can verify the PacketCommitment
|
|
||||||
for i, tc := range cases {
|
|
||||||
tc := tc
|
tc := tc
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
suite.Run(tc.msg, func() {
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
tc.malleate()
|
_, clientB, _, connB, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
|
connection := suite.chainB.GetConnection(connB)
|
||||||
// Set PacketCommitment on chainA
|
if tc.changeClientID {
|
||||||
connection := suite.oldchainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, types.OPEN)
|
connection.ClientID = ibctesting.InvalidID
|
||||||
suite.oldchainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.oldchainA.GetContext(), testPort1, testChannel1, 1, commitmentBz)
|
|
||||||
|
|
||||||
// Update ChainA client on chainB
|
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
|
||||||
|
|
||||||
// Check that ChainB can verify PacketCommitment stored in chainA
|
|
||||||
proof, proofHeight := queryProof(suite.oldchainA, commitmentKey)
|
|
||||||
// if testcase proofHeight is not 0, replace proofHeight with this value
|
|
||||||
if tc.proofHeight != 0 {
|
|
||||||
proofHeight = tc.proofHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := suite.oldchainB.App.IBCKeeper.ConnectionKeeper.VerifyPacketCommitment(
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100000, 0)
|
||||||
suite.oldchainB.GetContext(), connection, proofHeight+1, proof, testPort1,
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
testChannel1, 1, commitmentBz,
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
commitmentKey := host.KeyPacketCommitment(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
|
||||||
|
proof, proofHeight := suite.chainA.QueryProof(commitmentKey)
|
||||||
|
|
||||||
|
if tc.changePacketCommitmentState {
|
||||||
|
packet.Data = []byte(ibctesting.InvalidID)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = suite.chainB.App.IBCKeeper.ConnectionKeeper.VerifyPacketCommitment(
|
||||||
|
suite.chainB.GetContext(), connection, proofHeight+tc.heightDiff, proof,
|
||||||
|
packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), channeltypes.CommitPacket(packet),
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestVerifyPacketAcknowledgement has chainA verify the acknowledgement on
|
||||||
|
// channelB. The channels on chainA and chainB are fully opened and a packet
|
||||||
|
// is sent from chainA to chainB and received.
|
||||||
func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
|
func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
|
||||||
packetAckKey := host.KeyPacketAcknowledgement(testPort1, testChannel1, 1)
|
|
||||||
ack := []byte("acknowledgement")
|
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg string
|
msg string
|
||||||
proofHeight uint64
|
changeClientID bool
|
||||||
malleate func()
|
changeAcknowledgement bool
|
||||||
|
heightDiff uint64
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{"verification success", 0, func() {
|
{"verification success", false, false, 0, true},
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
{"client state not found- changed client ID", true, false, 0, false},
|
||||||
}, true},
|
{"consensus state not found - increased proof height", false, false, 5, false},
|
||||||
{"client state not found", 0, func() {}, false},
|
{"verification failed - changed acknowledgement", false, true, 0, false},
|
||||||
{"consensus state not found", 100, func() {
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
}, false},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range cases {
|
for _, tc := range cases {
|
||||||
tc := tc
|
tc := tc
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
suite.Run(tc.msg, func() {
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
tc.malleate()
|
clientA, clientB, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
connection := suite.oldchainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, types.OPEN)
|
connection := suite.chainA.GetConnection(connA)
|
||||||
suite.oldchainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.oldchainA.GetContext(), testPort1, testChannel1, 1, channeltypes.CommitAcknowledgement(ack))
|
if tc.changeClientID {
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
connection.ClientID = ibctesting.InvalidID
|
||||||
|
|
||||||
// TODO check this proof height
|
|
||||||
proof, proofHeight := queryProof(suite.oldchainA, packetAckKey)
|
|
||||||
// if testcase proofHeight is not 0, replace proofHeight with this value
|
|
||||||
if tc.proofHeight != 0 {
|
|
||||||
proofHeight = tc.proofHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := suite.oldchainB.App.IBCKeeper.ConnectionKeeper.VerifyPacketAcknowledgement(
|
// send and receive packet
|
||||||
suite.oldchainB.GetContext(), connection, proofHeight+1, proof, testPort1,
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100000, 0)
|
||||||
testChannel1, 1, ack,
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
err = suite.coordinator.PacketExecuted(suite.chainB, suite.chainA, packet, clientA)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
packetAckKey := host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
|
||||||
|
proof, proofHeight := suite.chainB.QueryProof(packetAckKey)
|
||||||
|
|
||||||
|
ack := ibctesting.TestHash
|
||||||
|
if tc.changeAcknowledgement {
|
||||||
|
ack = []byte(ibctesting.InvalidID)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyPacketAcknowledgement(
|
||||||
|
suite.chainA.GetContext(), connection, proofHeight+tc.heightDiff, proof,
|
||||||
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestVerifyPacketAcknowledgementAbsence has chainA verify the acknowledgement
|
||||||
|
// absence on channelB. The channels on chainA and chainB are fully opened and
|
||||||
|
// a packet is sent from chainA to chainB and not received.
|
||||||
func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
||||||
packetAckKey := host.KeyPacketAcknowledgement(testPort1, testChannel1, 1)
|
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg string
|
msg string
|
||||||
proofHeight uint64
|
changeClientID bool
|
||||||
malleate func()
|
recvAck bool
|
||||||
|
heightDiff uint64
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{"verification success", 0, func() {
|
{"verification success", false, false, 0, true},
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
{"client state not found - changed client ID", true, false, 0, false},
|
||||||
}, true},
|
{"consensus state not found - increased proof height", false, false, 5, false},
|
||||||
{"client state not found", 0, func() {}, false},
|
{"verification failed - acknowledgement was received", false, true, 0, false},
|
||||||
{"consensus state not found", 100, func() {
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
}, false},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range cases {
|
for _, tc := range cases {
|
||||||
tc := tc
|
tc := tc
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
suite.Run(tc.msg, func() {
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
tc.malleate()
|
clientA, clientB, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
connection := suite.oldchainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, types.OPEN)
|
connection := suite.chainA.GetConnection(connA)
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
if tc.changeClientID {
|
||||||
|
connection.ClientID = ibctesting.InvalidID
|
||||||
proof, proofHeight := queryProof(suite.oldchainA, packetAckKey)
|
|
||||||
// if testcase proofHeight is not 0, replace proofHeight with this value
|
|
||||||
if tc.proofHeight != 0 {
|
|
||||||
proofHeight = tc.proofHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := suite.oldchainB.App.IBCKeeper.ConnectionKeeper.VerifyPacketAcknowledgementAbsence(
|
// send, only receive if specified
|
||||||
suite.oldchainB.GetContext(), connection, proofHeight+1, proof, testPort1,
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100000, 0)
|
||||||
testChannel1, 1,
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
if tc.recvAck {
|
||||||
|
err = suite.coordinator.PacketExecuted(suite.chainB, suite.chainA, packet, clientA)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
// need to update height to prove absence
|
||||||
|
suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
|
||||||
|
suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, clientexported.Tendermint)
|
||||||
|
}
|
||||||
|
|
||||||
|
packetAckKey := host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
|
||||||
|
proof, proofHeight := suite.chainB.QueryProof(packetAckKey)
|
||||||
|
|
||||||
|
err = suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyPacketAcknowledgementAbsence(
|
||||||
|
suite.chainA.GetContext(), connection, proofHeight+tc.heightDiff, proof,
|
||||||
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestVerifyNextSequenceRecv has chainA verify the next sequence receive on
|
||||||
|
// channelB. The channels on chainA and chainB are fully opened and a packet
|
||||||
|
// is sent from chainA to chainB and received.
|
||||||
func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() {
|
func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() {
|
||||||
nextSeqRcvKey := host.KeyNextSequenceRecv(testPort1, testChannel1)
|
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
msg string
|
msg string
|
||||||
proofHeight uint64
|
changeClientID bool
|
||||||
malleate func()
|
offsetSeq uint64
|
||||||
|
heightDiff uint64
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{"verification success", uint64(0), func() {
|
{"verification success", false, 0, 0, true},
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
{"client state not found- changed client ID", true, 0, 0, false},
|
||||||
}, true},
|
{"consensus state not found - increased proof height", false, 0, 5, false},
|
||||||
{"client state not found", uint64(0), func() {}, false},
|
{"verification failed - wrong expected next seq recv", false, 1, 0, false},
|
||||||
{"consensus state not found", uint64(100), func() {
|
|
||||||
suite.oldchainB.CreateClient(suite.oldchainA)
|
|
||||||
}, false},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range cases {
|
for _, tc := range cases {
|
||||||
tc := tc
|
tc := tc
|
||||||
i := i
|
|
||||||
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
|
suite.Run(tc.msg, func() {
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
tc.malleate()
|
clientA, clientB, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
|
||||||
connection := suite.oldchainA.createConnection(testConnectionIDA, testConnectionIDB, testClientIDA, testClientIDB, types.OPEN)
|
connection := suite.chainA.GetConnection(connA)
|
||||||
suite.oldchainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.oldchainA.GetContext(), testPort1, testChannel1, 1)
|
if tc.changeClientID {
|
||||||
suite.oldchainB.updateClient(suite.oldchainA)
|
connection.ClientID = ibctesting.InvalidID
|
||||||
|
|
||||||
proof, proofHeight := queryProof(suite.oldchainA, nextSeqRcvKey)
|
|
||||||
// if testcase proofHeight is not 0, replace proofHeight with this value
|
|
||||||
if tc.proofHeight != 0 {
|
|
||||||
proofHeight = tc.proofHeight
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := suite.oldchainB.App.IBCKeeper.ConnectionKeeper.VerifyNextSequenceRecv(
|
// send and receive packet
|
||||||
suite.oldchainB.GetContext(), connection, proofHeight+1, proof, testPort1,
|
packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, 100000, 0)
|
||||||
testChannel1, 1,
|
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
err = suite.coordinator.PacketExecuted(suite.chainB, suite.chainA, packet, clientA)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
nextSeqRecvKey := host.KeyNextSequenceRecv(packet.GetDestPort(), packet.GetDestChannel())
|
||||||
|
proof, proofHeight := suite.chainB.QueryProof(nextSeqRecvKey)
|
||||||
|
|
||||||
|
err = suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyNextSequenceRecv(
|
||||||
|
suite.chainA.GetContext(), connection, proofHeight+tc.heightDiff, proof,
|
||||||
|
packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+tc.offsetSeq,
|
||||||
)
|
)
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,20 @@ func (chain *TestChain) QueryProof(key []byte) ([]byte, uint64) {
|
||||||
return proof, uint64(res.Height) + 1
|
return proof, uint64(res.Height) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryConsensusStateProof performs an abci query for a consensus state
|
||||||
|
// stored on the given clientID. The proof and consensusHeight are returned.
|
||||||
|
func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, uint64) {
|
||||||
|
// retrieve consensus state to provide proof for
|
||||||
|
consState, found := chain.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(chain.GetContext(), clientID)
|
||||||
|
require.True(chain.t, found)
|
||||||
|
|
||||||
|
consensusHeight := consState.GetHeight()
|
||||||
|
consensusKey := host.FullKeyClientPath(clientID, host.KeyConsensusState(consensusHeight))
|
||||||
|
proofConsensus, _ := chain.QueryProof(consensusKey)
|
||||||
|
|
||||||
|
return proofConsensus, consensusHeight
|
||||||
|
}
|
||||||
|
|
||||||
// NextBlock sets the last header to the current header and increments the current header to be
|
// NextBlock sets the last header to the current header and increments the current header to be
|
||||||
// at the next block height. It does not update the time as that is handled by the Coordinator.
|
// at the next block height. It does not update the time as that is handled by the Coordinator.
|
||||||
//
|
//
|
||||||
|
@ -384,13 +398,7 @@ func (chain *TestChain) ConnectionOpenTry(
|
||||||
connectionKey := host.KeyConnection(counterpartyConnection.ID)
|
connectionKey := host.KeyConnection(counterpartyConnection.ID)
|
||||||
proofInit, proofHeight := counterparty.QueryProof(connectionKey)
|
proofInit, proofHeight := counterparty.QueryProof(connectionKey)
|
||||||
|
|
||||||
// retrieve consensus state to provide proof for
|
proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID)
|
||||||
consState, found := counterparty.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(counterparty.GetContext(), counterpartyConnection.ClientID)
|
|
||||||
require.True(chain.t, found)
|
|
||||||
|
|
||||||
consensusHeight := consState.GetHeight()
|
|
||||||
consensusKey := host.FullKeyClientPath(counterpartyConnection.ClientID, host.KeyConsensusState(consensusHeight))
|
|
||||||
proofConsensus, _ := counterparty.QueryProof(consensusKey)
|
|
||||||
|
|
||||||
msg := connectiontypes.NewMsgConnectionOpenTry(
|
msg := connectiontypes.NewMsgConnectionOpenTry(
|
||||||
connection.ID, connection.ClientID,
|
connection.ID, connection.ClientID,
|
||||||
|
@ -411,13 +419,7 @@ func (chain *TestChain) ConnectionOpenAck(
|
||||||
connectionKey := host.KeyConnection(counterpartyConnection.ID)
|
connectionKey := host.KeyConnection(counterpartyConnection.ID)
|
||||||
proofTry, proofHeight := counterparty.QueryProof(connectionKey)
|
proofTry, proofHeight := counterparty.QueryProof(connectionKey)
|
||||||
|
|
||||||
// retrieve consensus state to provide proof for
|
proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID)
|
||||||
consState, found := counterparty.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(counterparty.GetContext(), counterpartyConnection.ClientID)
|
|
||||||
require.True(chain.t, found)
|
|
||||||
|
|
||||||
consensusHeight := consState.GetHeight()
|
|
||||||
consensusKey := host.FullKeyClientPath(counterpartyConnection.ClientID, host.KeyConsensusState(consensusHeight))
|
|
||||||
proofConsensus, _ := counterparty.QueryProof(consensusKey)
|
|
||||||
|
|
||||||
msg := connectiontypes.NewMsgConnectionOpenAck(
|
msg := connectiontypes.NewMsgConnectionOpenAck(
|
||||||
connection.ID,
|
connection.ID,
|
||||||
|
|
Loading…
Reference in New Issue