Some checks failed
CodeQL / Analyze (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
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
178 lines
6.5 KiB
Go
178 lines
6.5 KiB
Go
package migrations_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
testifysuite "github.com/stretchr/testify/suite"
|
|
|
|
clienttypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/02-client/types"
|
|
host "git.cw.tr/mukan-network/mukan-ibc/modules/core/24-host"
|
|
"git.cw.tr/mukan-network/mukan-ibc/modules/core/exported"
|
|
ibctm "git.cw.tr/mukan-network/mukan-ibc/modules/light-clients/07-tendermint"
|
|
ibctmmigrations "git.cw.tr/mukan-network/mukan-ibc/modules/light-clients/07-tendermint/migrations"
|
|
ibctesting "git.cw.tr/mukan-network/mukan-ibc/testing"
|
|
)
|
|
|
|
type MigrationsTestSuite struct {
|
|
testifysuite.Suite
|
|
|
|
coordinator *ibctesting.Coordinator
|
|
|
|
// testing chains used for convenience and readability
|
|
chainA *ibctesting.TestChain
|
|
chainB *ibctesting.TestChain
|
|
}
|
|
|
|
func (suite *MigrationsTestSuite) SetupTest() {
|
|
suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
|
|
suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1))
|
|
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2))
|
|
}
|
|
|
|
func TestTendermintTestSuite(t *testing.T) {
|
|
testifysuite.Run(t, new(MigrationsTestSuite))
|
|
}
|
|
|
|
// test pruning of multiple expired tendermint consensus states
|
|
func (suite *MigrationsTestSuite) TestPruneExpiredConsensusStates() {
|
|
// create multiple tendermint clients and a solo machine client
|
|
// the solo machine is used to verify this pruning function only modifies
|
|
// the tendermint store.
|
|
|
|
numTMClients := 3
|
|
paths := make([]*ibctesting.Path, numTMClients)
|
|
|
|
for i := range numTMClients {
|
|
path := ibctesting.NewPath(suite.chainA, suite.chainB)
|
|
path.SetupClients()
|
|
|
|
paths[i] = path
|
|
}
|
|
|
|
solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, ibctesting.DefaultSolomachineClientID, "testing", 1)
|
|
smClientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), solomachine.ClientID)
|
|
|
|
// set client state
|
|
bz, err := suite.chainA.App.AppCodec().MarshalInterface(solomachine.ClientState())
|
|
suite.Require().NoError(err)
|
|
smClientStore.Set(host.ClientStateKey(), bz)
|
|
|
|
bz, err = suite.chainA.App.AppCodec().MarshalInterface(solomachine.ConsensusState())
|
|
suite.Require().NoError(err)
|
|
smHeight := clienttypes.NewHeight(0, 1)
|
|
smClientStore.Set(host.ConsensusStateKey(smHeight), bz)
|
|
|
|
pruneHeightMap := make(map[*ibctesting.Path][]exported.Height)
|
|
unexpiredHeightMap := make(map[*ibctesting.Path][]exported.Height)
|
|
|
|
for _, path := range paths {
|
|
// collect all heights expected to be pruned
|
|
var pruneHeights []exported.Height
|
|
pruneHeights = append(pruneHeights, path.EndpointA.GetClientLatestHeight())
|
|
|
|
// these heights will be expired and also pruned
|
|
for range 3 {
|
|
err := path.EndpointA.UpdateClient()
|
|
suite.Require().NoError(err)
|
|
|
|
pruneHeights = append(pruneHeights, path.EndpointA.GetClientLatestHeight())
|
|
}
|
|
|
|
// double chedck all information is currently stored
|
|
for _, pruneHeight := range pruneHeights {
|
|
consState, ok := suite.chainA.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
|
|
suite.Require().True(ok)
|
|
suite.Require().NotNil(consState)
|
|
|
|
ctx := suite.chainA.GetContext()
|
|
clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
|
|
|
|
processedTime, ok := ibctm.GetProcessedTime(clientStore, pruneHeight)
|
|
suite.Require().True(ok)
|
|
suite.Require().NotNil(processedTime)
|
|
|
|
processedHeight, ok := ibctm.GetProcessedHeight(clientStore, pruneHeight)
|
|
suite.Require().True(ok)
|
|
suite.Require().NotNil(processedHeight)
|
|
|
|
expectedConsKey := ibctm.GetIterationKey(clientStore, pruneHeight)
|
|
suite.Require().NotNil(expectedConsKey)
|
|
}
|
|
pruneHeightMap[path] = pruneHeights
|
|
}
|
|
|
|
// Increment the time by a week
|
|
suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
|
|
|
|
for _, path := range paths {
|
|
// create the consensus state that can be used as trusted height for next update
|
|
var unexpiredHeights []exported.Height
|
|
err := path.EndpointA.UpdateClient()
|
|
suite.Require().NoError(err)
|
|
unexpiredHeights = append(unexpiredHeights, path.EndpointA.GetClientLatestHeight())
|
|
|
|
err = path.EndpointA.UpdateClient()
|
|
suite.Require().NoError(err)
|
|
unexpiredHeights = append(unexpiredHeights, path.EndpointA.GetClientLatestHeight())
|
|
|
|
unexpiredHeightMap[path] = unexpiredHeights
|
|
}
|
|
|
|
// Increment the time by another week, then update the client.
|
|
// This will cause the consensus states created before the first time increment
|
|
// to be expired
|
|
suite.coordinator.IncrementTimeBy(7 * 24 * time.Hour)
|
|
totalPruned, err := ibctmmigrations.PruneExpiredConsensusStates(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), suite.chainA.GetSimApp().IBCKeeper.ClientKeeper)
|
|
suite.Require().NoError(err)
|
|
suite.Require().NotZero(totalPruned)
|
|
|
|
for _, path := range paths {
|
|
ctx := suite.chainA.GetContext()
|
|
clientStore := suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(ctx, path.EndpointA.ClientID)
|
|
|
|
// ensure everything has been pruned
|
|
for i, pruneHeight := range pruneHeightMap[path] {
|
|
consState, ok := suite.chainA.GetConsensusState(path.EndpointA.ClientID, pruneHeight)
|
|
suite.Require().False(ok, i)
|
|
suite.Require().Nil(consState, i)
|
|
|
|
processedTime, ok := ibctm.GetProcessedTime(clientStore, pruneHeight)
|
|
suite.Require().False(ok, i)
|
|
suite.Require().Equal(uint64(0), processedTime, i)
|
|
|
|
processedHeight, ok := ibctm.GetProcessedHeight(clientStore, pruneHeight)
|
|
suite.Require().False(ok, i)
|
|
suite.Require().Nil(processedHeight, i)
|
|
|
|
expectedConsKey := ibctm.GetIterationKey(clientStore, pruneHeight)
|
|
suite.Require().Nil(expectedConsKey, i)
|
|
}
|
|
|
|
// ensure metadata is set for unexpired consensus state
|
|
for _, height := range unexpiredHeightMap[path] {
|
|
consState, ok := suite.chainA.GetConsensusState(path.EndpointA.ClientID, height)
|
|
suite.Require().True(ok)
|
|
suite.Require().NotNil(consState)
|
|
|
|
processedTime, ok := ibctm.GetProcessedTime(clientStore, height)
|
|
suite.Require().True(ok)
|
|
suite.Require().NotEqual(uint64(0), processedTime)
|
|
|
|
processedHeight, ok := ibctm.GetProcessedHeight(clientStore, height)
|
|
suite.Require().True(ok)
|
|
suite.Require().NotEqual(clienttypes.ZeroHeight(), processedHeight)
|
|
|
|
consKey := ibctm.GetIterationKey(clientStore, height)
|
|
suite.Require().Equal(host.ConsensusStateKey(height), consKey)
|
|
}
|
|
}
|
|
|
|
// verify that solomachine client and consensus state were not removed
|
|
smClientStore = suite.chainA.App.GetIBCKeeper().ClientKeeper.ClientStore(suite.chainA.GetContext(), solomachine.ClientID)
|
|
bz = smClientStore.Get(host.ClientStateKey())
|
|
suite.Require().NotEmpty(bz)
|
|
|
|
bz = smClientStore.Get(host.ConsensusStateKey(smHeight))
|
|
suite.Require().NotEmpty(bz)
|
|
}
|