Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update #264 - updates genesis and genesis tests #382

Merged
merged 49 commits into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
ba651e3
reformat consumer genesis test
sainoe Jul 18, 2022
a87495d
remove validator fill in of ExportAppStateAndValidators
sainoe Jul 19, 2022
e3919b5
checkpoint, testing export genesis consumer
sainoe Jul 25, 2022
3dcd610
test consumer export
sainoe Jul 27, 2022
a815a15
make pass the tests
sainoe Jul 29, 2022
b25f968
fix export height to valset update id in consumer
sainoe Aug 2, 2022
4a06760
pass the tests
sainoe Aug 3, 2022
7b48c09
pass the tests
sainoe Aug 3, 2022
1378a52
* Update the provider and consumer export/init genesis with the new C…
sainoe Aug 11, 2022
c3cfeb4
remove pendingVSCPackets
sainoe Aug 12, 2022
0e548e4
remove references in create consumer chain proposal setters and getters
sainoe Aug 22, 2022
9a70d95
merge with remotes
sainoe Aug 22, 2022
524a0aa
fix unchecked errors
sainoe Aug 22, 2022
2a670e0
Merge branch 'main' into sainoe/export-genesis
sainoe Sep 29, 2022
65dc723
fix iterator bug
sainoe Sep 29, 2022
c711ecb
fix last nits
sainoe Sep 29, 2022
a4e83d8
Merge remote-tracking branch 'upstream/main' into sainoe/export-genesis
sainoe Sep 29, 2022
ecb643a
fix linter
sainoe Sep 30, 2022
06b5df5
Fix conflicts and make pass the tests
sainoe Oct 3, 2022
4ec85d5
format provider genesis tests
sainoe Oct 3, 2022
8017c29
format consumer genesis tests
sainoe Oct 3, 2022
d62dc16
Merge branch 'main' into sainoe/export-genesis
jtremback Oct 4, 2022
f1a415e
clarify consumer keeper genesis
sainoe Oct 6, 2022
9ea6c5a
push missing merge commit
sainoe Oct 6, 2022
5f03831
remove unused test helpers
sainoe Oct 7, 2022
03c643c
Merge branch 'main' into sainoe/export-genesis-2
shaspitz Oct 7, 2022
eb59e50
Feat: update consumer init and export genesis
sainoe Nov 9, 2022
de20341
Revert "Feat: update consumer init and export genesis"
sainoe Nov 9, 2022
c856708
merge main
sainoe Nov 9, 2022
d3b5bef
* Add LastTransmissionBlockHeight to consumer genesis proto
sainoe Nov 7, 2022
c292da4
Update consumer init
sainoe Nov 9, 2022
74aa7e9
Update consumer genesis export
sainoe Nov 9, 2022
19e4b93
fix last nits
sainoe Nov 9, 2022
0599369
Fix consumer InitGenesis
sainoe Nov 10, 2022
de4a73e
Update comments in genesis.proto
sainoe Nov 10, 2022
30b141c
format consumer genesis test
sainoe Nov 10, 2022
0399487
update comments
sainoe Nov 10, 2022
255c96d
Update provider genesis comments
sainoe Nov 14, 2022
1d06cd7
fix small lint errs
shaspitz Nov 14, 2022
26ec9e8
Merge branch 'main' into sainoe/export-genesis-2
shaspitz Nov 14, 2022
ebd590b
Merge branch 'main' into sainoe/export-genesis-2
shaspitz Nov 15, 2022
d0d5db1
* Update consumer genesis validation
sainoe Nov 15, 2022
4aca97e
Document consumer genesis validation
sainoe Nov 17, 2022
fd9dc10
Document consumer genesis validation
sainoe Nov 17, 2022
50ae321
Merge branch 'main' into sainoe/export-genesis-2
sainoe Nov 18, 2022
af1aebb
Update after #448 merge
sainoe Nov 18, 2022
6d93504
Merge branch 'sainoe/export-genesis-2' into export-2-upstream
sainoe Nov 18, 2022
504c44c
Merge branch 'main' into sainoe/export-genesis-2
shaspitz Nov 18, 2022
aff5156
Update x/ccv/consumer/types/genesis.go
jtremback Nov 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions testutil/keeper/expectations.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types"
"github.com/golang/mock/gomock"

host "github.com/cosmos/ibc-go/v3/modules/core/24-host"
ccv "github.com/cosmos/interchain-security/x/ccv/types"

extra "github.com/oxyno-zeta/gomock-extra-matcher"
Expand Down Expand Up @@ -91,3 +92,23 @@ func GetMocksForStopConsumerChain(ctx sdk.Context, mocks *MockedKeepers) []*gomo
mocks.MockChannelKeeper.EXPECT().ChanCloseInit(ctx, ccv.ProviderPortID, "channelID", dummyCap).Times(1),
}
}

func ExpectLatestConsensusStateMock(ctx sdk.Context, mocks MockedKeepers, clientID string, consState *ibctmtypes.ConsensusState) *gomock.Call {
return mocks.MockClientKeeper.EXPECT().
GetLatestClientConsensusState(ctx, clientID).Return(consState, true).Times(1)
}

func ExpectGetClientStateMock(ctx sdk.Context, mocks MockedKeepers, clientID string, clientState *ibctmtypes.ClientState) *gomock.Call {
return mocks.MockClientKeeper.EXPECT().GetClientState(ctx, clientID).Return(clientState, true).Times(1)
}

func ExpectCreateClientMock(ctx sdk.Context, mocks MockedKeepers, clientID string, clientState *ibctmtypes.ClientState, consState *ibctmtypes.ConsensusState) *gomock.Call {

return mocks.MockClientKeeper.EXPECT().CreateClient(ctx, clientState, consState).Return(clientID, nil).Times(1)
}

func ExpectGetCapabilityMock(ctx sdk.Context, mocks MockedKeepers) *gomock.Call {
return mocks.MockScopedKeeper.EXPECT().GetCapability(
ctx, host.PortPath(ccv.ConsumerPortID),
).Return(nil, true).Times(1)
}
2 changes: 1 addition & 1 deletion x/ccv/consumer/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt
}

// export the current validator set
valset, err := k.GetValidatorUpdates(ctx)
valset, err := k.GetCurrentValidatorsAsABCIpdates(ctx)
sainoe marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
panic(fmt.Sprintf("fail to retrieve the validator set: %s", err))
}
Expand Down
197 changes: 117 additions & 80 deletions x/ccv/consumer/keeper/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
host "github.com/cosmos/ibc-go/v3/modules/core/24-host"
clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
commitmenttypes "github.com/cosmos/ibc-go/v3/modules/core/23-commitment/types"
ibctmtypes "github.com/cosmos/ibc-go/v3/modules/light-clients/07-tendermint/types"
testkeeper "github.com/cosmos/interchain-security/testutil/keeper"
consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper"
"github.com/cosmos/interchain-security/x/ccv/consumer/types"
ccv "github.com/cosmos/interchain-security/x/ccv/types"
utils "github.com/cosmos/interchain-security/x/ccv/utils"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
Expand All @@ -23,24 +26,39 @@ import (
testutil "github.com/cosmos/interchain-security/testutil/keeper"
)

// TestInitGenesis tests that a consumer chain is correctly initialised from genesis.
// It covers the cases where a chain is new or restarted which means that
// its CCV channel is already established.
func TestInitGenesis(t *testing.T) {
// create states to initialise a consumer chain from genesis

// store consumer chain states in variables

// create channel and client IDs for the consumer
channelID := "channelID"
clientID := "tendermint-07"

// create provider channel and client ids
provChannelID := "ChannelID"
provClientID := "tendermint-07"
// generate validator public key
pubKey, err := testutil.GenPubKey()
require.NoError(t, err)

// create validator set with single validator
validator := tmtypes.NewValidator(pubKey, 1)

// create consensus state using a single validator
consensusState := testutil.GetConsensusState(clientID, time.Time{}, validator)

// create a provider consensus state using a single validator
provConsState := ibctmtypes.NewConsensusState(
time.Time{},
commitmenttypes.NewMerkleRoot([]byte("apphash")),
tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}).Hash()[:],
)
// create a provider client state
provClientState := ibctmtypes.NewClientState(
"provider",
ibctmtypes.DefaultTrustLevel,
0,
stakingtypes.DefaultUnbondingTime,
time.Second*10,
clienttypes.Height{},
commitmenttypes.GetSDKSpecs(),
[]string{"upgrade", "upgradedIBCState"},
true,
true,
)
slashRequests := consumertypes.SlashRequests{
Requests: []consumertypes.SlashRequest{{Infraction: stakingtypes.Downtime}},
}
Expand All @@ -52,6 +70,8 @@ func TestInitGenesis(t *testing.T) {
// create paramameters for a new chain
params := types.NewParams(true, types.DefaultBlocksPerDistributionTransmission, "", "")

// define two test cases which respectively create a genesis struct, use it to call InitGenesis
// and finally check that the genesis states are imported in the consumer keeper stores
testCases := []struct {
name string
malleate func(sdk.Context, testutil.MockedKeepers)
Expand All @@ -62,50 +82,72 @@ func TestInitGenesis(t *testing.T) {
name: "restart a new chain",
malleate: func(ctx sdk.Context, mocks testutil.MockedKeepers) {
gomock.InOrder(
expectGetCapabilityMock(ctx, mocks),
expectCreateClientMock(ctx, mocks, "", clientID, validator),
testkeeper.ExpectGetCapabilityMock(ctx, mocks),
testkeeper.ExpectCreateClientMock(ctx, mocks, provClientID, provClientState, provConsState),
)
},
genesis: consumertypes.NewInitialGenesisState(testutil.GetClientState(""), consensusState,
[]abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, slashRequests, params),
// create a genesis for a new chain
genesis: consumertypes.NewInitialGenesisState(
provClientState,
provConsState,
[]abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)},
slashRequests,
params,
),

assertStates: func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) {
require.Equal(t, gs.Params, ck.GetParams(ctx))
require.Equal(t, ccv.ConsumerPortID, ck.GetPort(ctx))

ubdTime, found := ck.GetUnbondingTime(ctx)
// compute the consumer unbonding period as done in InitGenesis (x/ccv/consumer/keeper/genesis.go)
expectedUbdPeriod := utils.ComputeConsumerUnbondingPeriod(gs.ProviderClientState.UnbondingPeriod)
gotUbdPeriod, found := ck.GetUnbondingTime(ctx)

require.True(t, found)
require.Equal(t, gs.ProviderClientState.UnbondingPeriod, ubdTime)
require.Equal(t, expectedUbdPeriod, gotUbdPeriod)

require.Zero(t, ck.GetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight())))

cid, ok := ck.GetProviderClientID(ctx)
require.True(t, ok)
require.Equal(t, clientID, cid)
require.Equal(t, provClientID, cid)
},
}, {
name: "restart a chain with an already established channel",
malleate: func(ctx sdk.Context, mocks testutil.MockedKeepers) {
gomock.InOrder(
expectGetCapabilityMock(ctx, mocks),
expectLatestConsensusStateMock(ctx, mocks, clientID, validator),
expectGetClientStateMock(ctx, mocks, "", clientID),
testkeeper.ExpectGetCapabilityMock(ctx, mocks),
testkeeper.ExpectLatestConsensusStateMock(ctx, mocks, provClientID, provConsState),
testkeeper.ExpectGetClientStateMock(ctx, mocks, provClientID, provClientState),
)
},
genesis: consumertypes.NewRestartGenesisState(clientID, channelID,
[]consumertypes.MaturingVSCPacket{matPacket},
[]abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)},
[]consumertypes.HeightToValsetUpdateID{{ValsetUpdateId: matPacket.VscId, Height: uint64(0)}},
[]consumertypes.OutstandingDowntime{{ValidatorConsensusAddress: sdk.ConsAddress(validator.Bytes()).String()}},
params,
),
// create a genesis for a restarted chain
genesis: &consumertypes.GenesisState{
ProviderClientId: provClientID,
ProviderChannelId: provChannelID,
Params: params,
NewChain: false,
ProviderClientState: provClientState,
ProviderConsensusState: provConsState,
InitialValSet: []abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)},
OutstandingDowntimeSlashing: []consumertypes.OutstandingDowntime{
{ValidatorConsensusAddress: sdk.ConsAddress(validator.Bytes()).String()},
},
HeightToValsetUpdateId: []consumertypes.HeightToValsetUpdateID{
{ValsetUpdateId: matPacket.VscId, Height: uint64(0)},
},
MaturingPackets: []consumertypes.MaturingVSCPacket{matPacket},
},
assertStates: func(ctx sdk.Context, ck consumerkeeper.Keeper, gs *consumertypes.GenesisState) {
require.Equal(t, gs.Params, ck.GetParams(ctx))
require.Equal(t, ccv.ConsumerPortID, ck.GetPort(ctx))

ubdTime, found := ck.GetUnbondingTime(ctx)
// compute the consumer unbonding period as done in InitGenesis (x/ccv/consumer/keeper/genesis.go)
expectedUbdPeriod := utils.ComputeConsumerUnbondingPeriod(gs.ProviderClientState.UnbondingPeriod)
gotUbdPeriod, found := ck.GetUnbondingTime(ctx)

require.True(t, found)
require.Equal(t, testutil.GetClientState("").UnbondingPeriod, ubdTime)
require.Equal(t, expectedUbdPeriod, gotUbdPeriod)

// export states to genesis
require.Equal(t, matPacket.VscId, ck.GetHeightValsetUpdateID(ctx, uint64(0)))
Expand All @@ -128,21 +170,23 @@ func TestInitGenesis(t *testing.T) {
// test setup
tc.malleate(ctx, mocks)

// init the chain states using a genesis
// init chain states
consumerKeeper.InitGenesis(ctx, tc.genesis)

// assert states
// assert consumer keeper states
tc.assertStates(ctx, consumerKeeper, tc.genesis)
})
}
}

// TestExportGenesis tests that a consumer chain genesis is correctly exported to genesis
// It covers the cases where the chain's CCV channel is or isn't established
func TestExportGenesis(t *testing.T) {
// create consumer chain states to be stored and exported to genesis

clientID := "tendermint-07"
channelID := "channelID"

// define the states exported into genesis
// create provider channel and client ids
provClientID := "tendermint-07"
provChannelID := "provChannelID"
slashRequests := consumertypes.SlashRequests{
Requests: []consumertypes.SlashRequest{{Infraction: stakingtypes.Downtime}},
}
Expand All @@ -151,18 +195,36 @@ func TestExportGenesis(t *testing.T) {
VscId: uint64(1),
MaturityTime: uint64(time.Now().UnixNano()),
}

params := types.NewParams(true, types.DefaultBlocksPerDistributionTransmission, "", "")

// create a single validator
pubKey := ed25519.GenPrivKey().PubKey()
tmPK, err := cryptocodec.ToTmPubKeyInterface(pubKey)
require.NoError(t, err)
validator := tmtypes.NewValidator(tmPK, 1)
// create a provider consensus state using a single validator
provConsState := ibctmtypes.NewConsensusState(
time.Time{},
commitmenttypes.NewMerkleRoot([]byte("apphash")),
tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}).Hash()[:],
)
// create a provider client state
provClientState := ibctmtypes.NewClientState(
"provider",
ibctmtypes.DefaultTrustLevel,
0,
stakingtypes.DefaultUnbondingTime,
time.Second*10,
clienttypes.Height{},
commitmenttypes.GetSDKSpecs(),
[]string{"upgrade", "upgradedIBCState"},
true,
true,
)
// create paramameters for an enabled consumer chain
params := types.NewParams(true, types.DefaultBlocksPerDistributionTransmission, "", "")

// create consensus state using a single validator
consensusState := testutil.GetConsensusState(clientID, time.Time{}, validator)

// define two test cases which respectively populate the consumer chain store
// using the states declared above then call ExportGenesis to finally check
// that the resulting genesis struct stores this same states
testCases := []struct {
name string
malleate func(sdk.Context, consumerkeeper.Keeper, testutil.MockedKeepers)
Expand All @@ -175,40 +237,39 @@ func TestExportGenesis(t *testing.T) {
cVal, err := consumertypes.NewCCValidator(validator.Address.Bytes(), 1, pubKey)
require.NoError(t, err)
ck.SetCCValidator(ctx, cVal)
ck.SetProviderClientID(ctx, clientID)
ck.SetProviderClientID(ctx, provClientID)
ck.SetPendingSlashRequests(
ctx,
slashRequests,
)

// set the mock calls executed during the export
gomock.InOrder(
expectGetClientStateMock(ctx, mocks, "", clientID),
expectLatestConsensusStateMock(ctx, mocks, clientID, validator),
testkeeper.ExpectGetClientStateMock(ctx, mocks, provClientID, provClientState),
testkeeper.ExpectLatestConsensusStateMock(ctx, mocks, provClientID, provConsState),
)
},

expGenesis: consumertypes.NewInitialGenesisState(testutil.GetClientState(""), consensusState,
expGenesis: consumertypes.NewInitialGenesisState(provClientState, provConsState,
[]abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)}, slashRequests, params),
},
{
name: "export a chain that has an established CCV channel",
malleate: func(ctx sdk.Context, ck consumerkeeper.Keeper, mocks testutil.MockedKeepers) {
// populate the states used by a running chain
// populate the states used by a restarted chain
cVal, err := consumertypes.NewCCValidator(validator.Address.Bytes(), 1, pubKey)
require.NoError(t, err)
ck.SetCCValidator(ctx, cVal)
ck.SetOutstandingDowntime(ctx, sdk.ConsAddress(validator.Address.Bytes()))

// populate the required states to simulate a completed handshake
ck.SetProviderClientID(ctx, clientID)
ck.SetProviderChannel(ctx, channelID)
// populate the required states for an established CCV channel
ck.SetProviderClientID(ctx, provClientID)
ck.SetProviderChannel(ctx, provChannelID)
ck.SetHeightValsetUpdateID(ctx, restartHeight, matPacket.VscId)
ck.SetPacketMaturityTime(ctx, matPacket.VscId, matPacket.MaturityTime)
},
expGenesis: consumertypes.NewRestartGenesisState(
clientID,
channelID,
provClientID,
provChannelID,
[]consumertypes.MaturingVSCPacket{matPacket},
[]abci.ValidatorUpdate{tmtypes.TM2PB.ValidatorUpdate(validator)},
[]types.HeightToValsetUpdateID{{Height: restartHeight, ValsetUpdateId: matPacket.VscId}},
Expand All @@ -231,35 +292,11 @@ func TestExportGenesis(t *testing.T) {
// test setup
tc.malleate(ctx, consumerKeeper, mocks)

// export staet to genesis
// export states to genesis
gotGen := consumerKeeper.ExportGenesis(ctx)

// check the obtained genesis
// check obtained genesis
require.EqualValues(t, tc.expGenesis, gotGen)
})
}
}

func expectLatestConsensusStateMock(ctx sdk.Context, mocks testutil.MockedKeepers, clientID string, vals ...*tmtypes.Validator) *gomock.Call {
consState := testutil.GetConsensusState(clientID, time.Time{}, vals...)
return mocks.MockClientKeeper.EXPECT().
GetLatestClientConsensusState(ctx, clientID).Return(consState, true).Times(1)
}

func expectGetClientStateMock(ctx sdk.Context, mocks testutil.MockedKeepers, chainID, clientID string) *gomock.Call {
cs := testutil.GetClientState(chainID)
return mocks.MockClientKeeper.EXPECT().GetClientState(ctx, clientID).Return(cs, true).Times(1)
}

func expectCreateClientMock(ctx sdk.Context, mocks testutil.MockedKeepers, chainID, clientID string, vals ...*tmtypes.Validator) *gomock.Call {
cs := testutil.GetClientState(chainID)
consState := testutil.GetConsensusState(clientID, time.Time{}, vals...)

return mocks.MockClientKeeper.EXPECT().CreateClient(ctx, cs, consState).Return(clientID, nil).Times(1)
}

func expectGetCapabilityMock(ctx sdk.Context, mocks testutil.MockedKeepers) *gomock.Call {
return mocks.MockScopedKeeper.EXPECT().GetCapability(
ctx, host.PortPath(ccv.ConsumerPortID),
).Return(nil, true).Times(1)
}
4 changes: 2 additions & 2 deletions x/ccv/consumer/keeper/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ func (k Keeper) TrackHistoricalInfo(ctx sdk.Context) {
k.SetHistoricalInfo(ctx, ctx.BlockHeight(), &historicalEntry)
}

// ValidatorUpdates gets all cross-chain validators converted to the ABCI validator update type
func (k Keeper) GetValidatorUpdates(ctx sdk.Context) ([]abci.ValidatorUpdate, error) {
// GetCurrentValidatorsAsABCIpdates gets all cross-chain validators converted to the ABCI validator update type
func (k Keeper) GetCurrentValidatorsAsABCIpdates(ctx sdk.Context) ([]abci.ValidatorUpdate, error) {
vals := k.GetAllCCValidator(ctx)
valUpdates := make([]abci.ValidatorUpdate, 0, len(vals))
for _, v := range vals {
Expand Down
Loading