Some checks failed
CodeQL / Analyze (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Deploy to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
Buf-Push / push (push) Has been cancelled
369 lines
12 KiB
Go
369 lines
12 KiB
Go
package localhost_test
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
testifysuite "github.com/stretchr/testify/suite"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"
|
|
connectiontypes "github.com/cosmos/ibc-go/v10/modules/core/03-connection/types"
|
|
channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types"
|
|
commitmenttypes "github.com/cosmos/ibc-go/v10/modules/core/23-commitment/types"
|
|
host "github.com/cosmos/ibc-go/v10/modules/core/24-host"
|
|
"github.com/cosmos/ibc-go/v10/modules/core/exported"
|
|
localhost "github.com/cosmos/ibc-go/v10/modules/light-clients/09-localhost"
|
|
ibctesting "github.com/cosmos/ibc-go/v10/testing"
|
|
"github.com/cosmos/ibc-go/v10/testing/mock"
|
|
)
|
|
|
|
type LocalhostTestSuite struct {
|
|
testifysuite.Suite
|
|
|
|
coordinator ibctesting.Coordinator
|
|
chain *ibctesting.TestChain
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) SetupTest() {
|
|
suite.coordinator = *ibctesting.NewCoordinator(suite.T(), 1)
|
|
suite.chain = suite.coordinator.GetChain(ibctesting.GetChainID(1))
|
|
}
|
|
|
|
func TestLocalhostTestSuite(t *testing.T) {
|
|
testifysuite.Run(t, new(LocalhostTestSuite))
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestInitialize() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
err = lightClientModule.Initialize(suite.chain.GetContext(), exported.LocalhostClientID, nil, nil)
|
|
suite.Require().Error(err)
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestVerifyClientMessage() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
err = lightClientModule.VerifyClientMessage(suite.chain.GetContext(), exported.LocalhostClientID, nil)
|
|
suite.Require().Error(err)
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestVerifyCheckForMisbehaviour() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().False(lightClientModule.CheckForMisbehaviour(suite.chain.GetContext(), exported.LocalhostClientID, nil))
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestUpdateState() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
heights := lightClientModule.UpdateState(suite.chain.GetContext(), exported.LocalhostClientID, nil)
|
|
|
|
expHeight := clienttypes.NewHeight(1, uint64(suite.chain.GetContext().BlockHeight()))
|
|
suite.Require().True(heights[0].EQ(expHeight))
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestVerifyMembership() {
|
|
var (
|
|
path exported.Path
|
|
value []byte
|
|
)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expErr error
|
|
}{
|
|
{
|
|
"success: connection state verification",
|
|
func() {
|
|
connectionEnd := connectiontypes.NewConnectionEnd(
|
|
connectiontypes.OPEN,
|
|
exported.LocalhostClientID,
|
|
connectiontypes.NewCounterparty(exported.LocalhostClientID, exported.LocalhostConnectionID, suite.chain.GetPrefix()),
|
|
connectiontypes.GetCompatibleVersions(), 0,
|
|
)
|
|
|
|
suite.chain.GetSimApp().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chain.GetContext(), exported.LocalhostConnectionID, connectionEnd)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.ConnectionKey(exported.LocalhostConnectionID))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
value = suite.chain.Codec.MustMarshal(&connectionEnd)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"success: channel state verification",
|
|
func() {
|
|
channel := channeltypes.NewChannel(
|
|
channeltypes.OPEN,
|
|
channeltypes.UNORDERED,
|
|
channeltypes.NewCounterparty(mock.PortID, ibctesting.FirstChannelID),
|
|
[]string{exported.LocalhostConnectionID},
|
|
mock.Version,
|
|
)
|
|
|
|
suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, channel)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.ChannelKey(mock.PortID, ibctesting.FirstChannelID))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
value = suite.chain.Codec.MustMarshal(&channel)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"success: next sequence recv verification",
|
|
func() {
|
|
nextSeqRecv := uint64(100)
|
|
suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetNextSequenceRecv(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, nextSeqRecv)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.NextSequenceRecvKey(mock.PortID, ibctesting.FirstChannelID))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
value = sdk.Uint64ToBigEndian(nextSeqRecv)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"success: packet commitment verification",
|
|
func() {
|
|
packet := channeltypes.NewPacket(
|
|
ibctesting.MockPacketData,
|
|
1,
|
|
ibctesting.MockPort,
|
|
ibctesting.FirstChannelID,
|
|
ibctesting.MockPort,
|
|
ibctesting.FirstChannelID,
|
|
clienttypes.NewHeight(0, 10),
|
|
0,
|
|
)
|
|
|
|
commitmentBz := channeltypes.CommitPacket(packet)
|
|
suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketCommitment(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, 1, commitmentBz)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
value = commitmentBz
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"success: packet acknowledgement verification",
|
|
func() {
|
|
suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, 1, ibctesting.MockAcknowledgement)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(mock.PortID, ibctesting.FirstChannelID, 1))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
value = ibctesting.MockAcknowledgement
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"failure: invalid type for key path",
|
|
func() {
|
|
path = mock.KeyPath{}
|
|
},
|
|
errors.New("expected v2.MerklePath, got mock.KeyPath: invalid type"),
|
|
},
|
|
{
|
|
"failure: key path has too many elements",
|
|
func() {
|
|
path = commitmenttypes.NewMerklePath([]byte("ibc"), []byte("test"), []byte("key"))
|
|
},
|
|
errors.New("invalid path"),
|
|
},
|
|
{
|
|
"failure: no value found at provided key path",
|
|
func() {
|
|
merklePath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementKey(mock.PortID, ibctesting.FirstChannelID, 100))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
value = ibctesting.MockAcknowledgement
|
|
},
|
|
errors.New("value not found for path"),
|
|
},
|
|
{
|
|
"failure: invalid value, bytes are not equal",
|
|
func() {
|
|
channel := channeltypes.NewChannel(
|
|
channeltypes.OPEN,
|
|
channeltypes.UNORDERED,
|
|
channeltypes.NewCounterparty(mock.PortID, ibctesting.FirstChannelID),
|
|
[]string{exported.LocalhostConnectionID},
|
|
mock.Version,
|
|
)
|
|
|
|
suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, channel)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.ChannelKey(mock.PortID, ibctesting.FirstChannelID))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
|
|
// modify the channel before marshalling to value bz
|
|
channel.State = channeltypes.CLOSED
|
|
value = suite.chain.Codec.MustMarshal(&channel)
|
|
},
|
|
errors.New("value provided does not equal value stored at path"),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest()
|
|
|
|
tc.malleate()
|
|
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
err = lightClientModule.VerifyMembership(
|
|
suite.chain.GetContext(),
|
|
exported.LocalhostClientID,
|
|
clienttypes.ZeroHeight(),
|
|
0, 0, // use zero values for delay periods
|
|
localhost.SentinelProof,
|
|
path,
|
|
value,
|
|
)
|
|
|
|
if tc.expErr == nil {
|
|
suite.Require().NoError(err)
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.ErrorContains(err, tc.expErr.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestVerifyNonMembership() {
|
|
var path exported.Path
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expError error
|
|
}{
|
|
{
|
|
"success: packet receipt absence verification",
|
|
func() {
|
|
merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptKey(mock.PortID, ibctesting.FirstChannelID, 1))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"packet receipt absence verification fails",
|
|
func() {
|
|
suite.chain.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chain.GetContext(), mock.PortID, ibctesting.FirstChannelID, 1)
|
|
|
|
merklePath := commitmenttypes.NewMerklePath(host.PacketReceiptKey(mock.PortID, ibctesting.FirstChannelID, 1))
|
|
merklePath, err := commitmenttypes.ApplyPrefix(suite.chain.GetPrefix(), merklePath)
|
|
suite.Require().NoError(err)
|
|
|
|
path = merklePath
|
|
},
|
|
errors.New("non-membership verification failed"),
|
|
},
|
|
{
|
|
"invalid type for key path",
|
|
func() {
|
|
path = mock.KeyPath{}
|
|
},
|
|
errors.New("expected v2.MerklePath, got mock.KeyPath: invalid type"),
|
|
},
|
|
{
|
|
"key path has too many elements",
|
|
func() {
|
|
path = commitmenttypes.NewMerklePath([]byte("ibc"), []byte("test"), []byte("key"))
|
|
},
|
|
errors.New("invalid path"),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest()
|
|
|
|
tc.malleate()
|
|
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
err = lightClientModule.VerifyNonMembership(
|
|
suite.chain.GetContext(),
|
|
exported.LocalhostClientID,
|
|
clienttypes.ZeroHeight(),
|
|
0, 0, // use zero values for delay periods
|
|
localhost.SentinelProof,
|
|
path,
|
|
)
|
|
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.ErrorContains(err, tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestStatus() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(exported.Active, lightClientModule.Status(suite.chain.GetContext(), exported.LocalhostClientID))
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestGetTimestampAtHeight() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
ctx := suite.chain.GetContext()
|
|
timestamp, err := lightClientModule.TimestampAtHeight(ctx, exported.LocalhostClientID, nil)
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(uint64(ctx.BlockTime().UnixNano()), timestamp)
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestRecoverClient() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
err = lightClientModule.RecoverClient(suite.chain.GetContext(), exported.LocalhostClientID, exported.LocalhostClientID)
|
|
suite.Require().Error(err)
|
|
}
|
|
|
|
func (suite *LocalhostTestSuite) TestVerifyUpgradeAndUpdateState() {
|
|
lightClientModule, err := suite.chain.App.GetIBCKeeper().ClientKeeper.Route(suite.chain.GetContext(), exported.LocalhostClientID)
|
|
suite.Require().NoError(err)
|
|
|
|
err = lightClientModule.VerifyUpgradeAndUpdateState(suite.chain.GetContext(), exported.LocalhostClientID, nil, nil, nil, nil)
|
|
suite.Require().Error(err)
|
|
}
|