-
Notifications
You must be signed in to change notification settings - Fork 138
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
Changes from 40 commits
ba651e3
a87495d
e3919b5
3dcd610
a815a15
b25f968
4a06760
7b48c09
1378a52
c3cfeb4
0e548e4
9a70d95
524a0aa
2a670e0
65dc723
c711ecb
a4e83d8
ecb643a
06b5df5
4ec85d5
8017c29
d62dc16
f1a415e
9ea6c5a
5f03831
03c643c
eb59e50
de20341
c856708
d3b5bef
c292da4
74aa7e9
19e4b93
0599369
de4a73e
30b141c
0399487
255c96d
1d06cd7
26ec9e8
ebd590b
d0d5db1
4aca97e
fd9dc10
50ae321
af1aebb
6d93504
504c44c
aff5156
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,11 +21,6 @@ func (suite *CCVTestSuite) TestConsumerGenesis() { | |
|
||
genesis := consumerKeeper.ExportGenesis(suite.consumerChain.GetContext()) | ||
|
||
// Confirm that client and cons state are exported from consumer keeper properly | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this deletion intentional? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. The client and last consensus states are exported by the IBC module during the genesis export. A consumer genesis should only have these states fill in for a new chain start. |
||
consumerEndpointClientState, consumerEndpointConsState := suite.GetConsumerEndpointClientAndConsState() | ||
suite.Require().Equal(consumerEndpointClientState, genesis.ProviderClientState) | ||
suite.Require().Equal(consumerEndpointConsState, genesis.ProviderConsensusState) | ||
|
||
suite.Require().NotPanics(func() { | ||
consumerKeeper.InitGenesis(suite.consumerChain.GetContext(), genesis) | ||
// reset suite to reset provider client | ||
|
@@ -39,9 +34,8 @@ func (suite *CCVTestSuite) TestConsumerGenesis() { | |
|
||
clientId, ok := consumerKeeper.GetProviderClientID(ctx) | ||
suite.Require().True(ok) | ||
clientState, ok := suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) | ||
_, ok = suite.consumerApp.GetIBCKeeper().ClientKeeper.GetClientState(ctx, clientId) | ||
suite.Require().True(ok) | ||
suite.Require().Equal(genesis.ProviderClientState, clientState, "client state not set correctly after InitGenesis") | ||
|
||
suite.SetupCCVChannel() | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -15,6 +15,11 @@ import ( | |||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// InitGenesis initializes the CCV consumer state and binds to PortID. | ||||||||||||||||||||||||||||||||||
// The three states in which a consumer chain can start/restart: | ||||||||||||||||||||||||||||||||||
// | ||||||||||||||||||||||||||||||||||
// 1. A client to the provider was never created, i.e. a new consumer chain is started for the first time. | ||||||||||||||||||||||||||||||||||
// 2. A consumer chain restarts after a client to the provider was created, but the CCV channel handshake is still in progress | ||||||||||||||||||||||||||||||||||
// 3. A consumer chain restarts after the CCV channel handshake was completed. | ||||||||||||||||||||||||||||||||||
func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) []abci.ValidatorUpdate { | ||||||||||||||||||||||||||||||||||
k.SetParams(ctx, state.Params) | ||||||||||||||||||||||||||||||||||
// TODO: Remove enabled flag and find a better way to setup e2e tests | ||||||||||||||||||||||||||||||||||
|
@@ -37,39 +42,51 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) | |||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// initialValSet is checked in NewChain case by ValidateGenesis | ||||||||||||||||||||||||||||||||||
// start a new chain | ||||||||||||||||||||||||||||||||||
if state.NewChain { | ||||||||||||||||||||||||||||||||||
// Create the provider client in InitGenesis for new consumer chain. CCV Handshake must be established with this client id. | ||||||||||||||||||||||||||||||||||
// create the provider client in InitGenesis for new consumer chain. CCV Handshake must be established with this client id. | ||||||||||||||||||||||||||||||||||
clientID, err := k.clientKeeper.CreateClient(ctx, state.ProviderClientState, state.ProviderConsensusState) | ||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||
panic(err) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// Set default value for valset update ID | ||||||||||||||||||||||||||||||||||
k.SetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight()), uint64(0)) | ||||||||||||||||||||||||||||||||||
// set provider client id. | ||||||||||||||||||||||||||||||||||
k.SetProviderClientID(ctx, clientID) | ||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||
// verify that latest consensus state on provider client matches the initial validator set of restarted chain | ||||||||||||||||||||||||||||||||||
// thus, IBC genesis MUST run before CCV consumer genesis | ||||||||||||||||||||||||||||||||||
consState, ok := k.clientKeeper.GetLatestClientConsensusState(ctx, state.ProviderClientId) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
panic("consensus state for provider client not found. MUST run IBC genesis before CCV consumer genesis") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
tmConsState, ok := consState.(*ibctmtypes.ConsensusState) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
panic(fmt.Sprintf("consensus state has wrong type. expected: %T, got: %T", &ibctmtypes.ConsensusState{}, consState)) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the switch? Were they not working in the other order? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wdym? |
||||||||||||||||||||||||||||||||||
// ensure that initial validator set is same as initial consensus state on provider client. | ||||||||||||||||||||||||||||||||||
// this will be verified by provider module on channel handshake. | ||||||||||||||||||||||||||||||||||
vals, err := tmtypes.PB2TM.ValidatorUpdates(state.InitialValSet) | ||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||
// set default value for valset update ID | ||||||||||||||||||||||||||||||||||
k.SetHeightValsetUpdateID(ctx, uint64(ctx.BlockHeight()), uint64(0)) | ||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||
// verify genesis initial valset against the latest consensus state | ||||||||||||||||||||||||||||||||||
// IBC genesis MUST run before CCV consumer genesis | ||||||||||||||||||||||||||||||||||
if err := k.verifyGenesisInitValset(ctx, state); err != nil { | ||||||||||||||||||||||||||||||||||
panic(err) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
valSet := tmtypes.NewValidatorSet(vals) | ||||||||||||||||||||||||||||||||||
// chain restarts without the CCV channel established | ||||||||||||||||||||||||||||||||||
if state.ProviderChannelId == "" { | ||||||||||||||||||||||||||||||||||
k.SetPendingSlashRequests(ctx, state.PendingSlashRequests) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// chain restarts with the CCV channel established | ||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So i guess you don't even have to deal with the case where the handshake is in progress because it will just take care of itself? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This case is detected when the channelID is empty and only these states are getting populated: interchain-security/x/ccv/consumer/keeper/genesis.go Lines 64 to 67 in 26ec9e8
interchain-security/x/ccv/consumer/keeper/genesis.go Lines 92 to 103 in 26ec9e8
Note that the client to the provider is already created and imported by the IBC module genesis in this case. |
||||||||||||||||||||||||||||||||||
// set provider channel ID | ||||||||||||||||||||||||||||||||||
k.SetProviderChannel(ctx, state.ProviderChannelId) | ||||||||||||||||||||||||||||||||||
// set all unbonding sequences | ||||||||||||||||||||||||||||||||||
for _, mp := range state.MaturingPackets { | ||||||||||||||||||||||||||||||||||
k.SetPacketMaturityTime(ctx, mp.VscId, mp.MaturityTime) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
// set outstanding downtime slashing requests | ||||||||||||||||||||||||||||||||||
for _, od := range state.OutstandingDowntimeSlashing { | ||||||||||||||||||||||||||||||||||
consAddr, err := sdk.ConsAddressFromBech32(od.ValidatorConsensusAddress) | ||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||
panic(err) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
k.SetOutstandingDowntime(ctx, consAddr) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
// set last transmission block height | ||||||||||||||||||||||||||||||||||
err := k.SetLastTransmissionBlockHeight(ctx, state.LastTransmissionBlockHeight) | ||||||||||||||||||||||||||||||||||
Comment on lines
+82
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this code work for a zero height restart? Does it even need to work for a zero height restart? note sure... |
||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||
panic(fmt.Sprintf("could not set last transmission block height: %v", err)) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
if !bytes.Equal(tmConsState.NextValidatorsHash, valSet.Hash()) { | ||||||||||||||||||||||||||||||||||
panic("initial validator set does not match last consensus state of the provider client") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// set height to valset update id mapping | ||||||||||||||||||||||||||||||||||
|
@@ -79,12 +96,7 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) | |||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// set provider client id | ||||||||||||||||||||||||||||||||||
k.SetProviderClientID(ctx, state.ProviderClientId) | ||||||||||||||||||||||||||||||||||
// set provider channel id. | ||||||||||||||||||||||||||||||||||
k.SetProviderChannel(ctx, state.ProviderChannelId) | ||||||||||||||||||||||||||||||||||
// set all unbonding sequences | ||||||||||||||||||||||||||||||||||
for _, mp := range state.MaturingPackets { | ||||||||||||||||||||||||||||||||||
k.SetPacketMaturityTime(ctx, mp.VscId, mp.MaturityTime) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// populate cross chain validators states with initial valset | ||||||||||||||||||||||||||||||||||
|
@@ -93,16 +105,15 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) | |||||||||||||||||||||||||||||||||
return state.InitialValSet | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// ExportGenesis exports the CCV consumer state. If the channel has already been established, then we export | ||||||||||||||||||||||||||||||||||
// provider chain. Otherwise, this is still considered a new chain and we export latest client state. | ||||||||||||||||||||||||||||||||||
// ExportGenesis returns the CCV consumer module's exported genesis | ||||||||||||||||||||||||||||||||||
func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisState) { | ||||||||||||||||||||||||||||||||||
params := k.GetParams(ctx) | ||||||||||||||||||||||||||||||||||
if !params.Enabled { | ||||||||||||||||||||||||||||||||||
return consumertypes.DefaultGenesisState() | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// export the current validator set | ||||||||||||||||||||||||||||||||||
valset, err := k.GetValidatorUpdates(ctx) | ||||||||||||||||||||||||||||||||||
valset, err := k.GetCurrentValidatorsAsABCIUpdates(ctx) | ||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||
panic(fmt.Sprintf("fail to retrieve the validator set: %s", err)) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
@@ -124,16 +135,6 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt | |||||||||||||||||||||||||||||||||
return false | ||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
heightToVCIDs := []types.HeightToValsetUpdateID{} | ||||||||||||||||||||||||||||||||||
k.IterateHeightToValsetUpdateID(ctx, func(height, vscID uint64) bool { | ||||||||||||||||||||||||||||||||||
hv := types.HeightToValsetUpdateID{ | ||||||||||||||||||||||||||||||||||
Height: height, | ||||||||||||||||||||||||||||||||||
ValsetUpdateId: vscID, | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
heightToVCIDs = append(heightToVCIDs, hv) | ||||||||||||||||||||||||||||||||||
return true | ||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
outstandingDowntimes := []types.OutstandingDowntime{} | ||||||||||||||||||||||||||||||||||
k.IterateOutstandingDowntime(ctx, func(addr string) bool { | ||||||||||||||||||||||||||||||||||
od := types.OutstandingDowntime{ | ||||||||||||||||||||||||||||||||||
|
@@ -148,36 +149,60 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt | |||||||||||||||||||||||||||||||||
channelID, | ||||||||||||||||||||||||||||||||||
maturingPackets, | ||||||||||||||||||||||||||||||||||
valset, | ||||||||||||||||||||||||||||||||||
heightToVCIDs, | ||||||||||||||||||||||||||||||||||
k.GetHeightToValsetUpdateIDs(ctx), | ||||||||||||||||||||||||||||||||||
consumertypes.SlashRequests{}, | ||||||||||||||||||||||||||||||||||
outstandingDowntimes, | ||||||||||||||||||||||||||||||||||
consumertypes.LastTransmissionBlockHeight{}, | ||||||||||||||||||||||||||||||||||
params, | ||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||
clientID, ok := k.GetProviderClientID(ctx) | ||||||||||||||||||||||||||||||||||
// if provider clientID and channelID don't exist on the consumer chain, then CCV protocol is disabled for this chain | ||||||||||||||||||||||||||||||||||
// return a disabled genesis state | ||||||||||||||||||||||||||||||||||
// if provider clientID and channelID don't exist on the consumer chain, | ||||||||||||||||||||||||||||||||||
// then CCV protocol is disabled for this chain return a default genesis state | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
return consumertypes.DefaultGenesisState() | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
cs, ok := k.clientKeeper.GetClientState(ctx, clientID) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
panic("provider client not set on already running consumer chain") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
tmCs, ok := cs.(*ibctmtypes.ClientState) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
panic("provider client consensus state is not tendermint client state") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
consState, ok := k.clientKeeper.GetLatestClientConsensusState(ctx, clientID) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
panic("provider consensus state not set on already running consumer chain") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
tmConsState, ok := consState.(*ibctmtypes.ConsensusState) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
panic("provider consensus state is not tendermint consensus state") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// export client states and pending slashing requests into a new chain genesis | ||||||||||||||||||||||||||||||||||
genesis = consumertypes.NewInitialGenesisState(tmCs, tmConsState, valset, k.GetPendingSlashRequests(ctx), params) | ||||||||||||||||||||||||||||||||||
genesis = consumertypes.NewRestartGenesisState( | ||||||||||||||||||||||||||||||||||
clientID, | ||||||||||||||||||||||||||||||||||
"", | ||||||||||||||||||||||||||||||||||
nil, | ||||||||||||||||||||||||||||||||||
valset, | ||||||||||||||||||||||||||||||||||
k.GetHeightToValsetUpdateIDs(ctx), | ||||||||||||||||||||||||||||||||||
k.GetPendingSlashRequests(ctx), | ||||||||||||||||||||||||||||||||||
nil, | ||||||||||||||||||||||||||||||||||
consumertypes.LastTransmissionBlockHeight{}, | ||||||||||||||||||||||||||||||||||
params, | ||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// verifyGenesisInitValset verifies the latest consensus state on provider client matches | ||||||||||||||||||||||||||||||||||
// the initial validator set of restarted chain thus | ||||||||||||||||||||||||||||||||||
func (k Keeper) verifyGenesisInitValset(ctx sdk.Context, genState *consumertypes.GenesisState) error { | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
consState, ok := k.clientKeeper.GetLatestClientConsensusState(ctx, genState.ProviderClientId) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
return fmt.Errorf("consensus state for provider client not found. MUST run IBC genesis before CCV consumer genesis") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
tmConsState, ok := consState.(*ibctmtypes.ConsensusState) | ||||||||||||||||||||||||||||||||||
if !ok { | ||||||||||||||||||||||||||||||||||
return fmt.Errorf(fmt.Sprintf("consensus state has wrong type. expected: %T, got: %T", &ibctmtypes.ConsensusState{}, consState)) | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
// ensure that initial validator set is same as initial consensus state on provider client. | ||||||||||||||||||||||||||||||||||
// this will be verified by provider module on channel handshake. | ||||||||||||||||||||||||||||||||||
vals, err := tmtypes.PB2TM.ValidatorUpdates(genState.InitialValSet) | ||||||||||||||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||||||||||||||
return err | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
valSet := tmtypes.NewValidatorSet(vals) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
if !bytes.Equal(tmConsState.NextValidatorsHash, valSet.Hash()) { | ||||||||||||||||||||||||||||||||||
return fmt.Errorf("initial validator set does not match last consensus state of the provider client") | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
return nil | ||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this being used for a zero height restart or a restart containing the current block height? Or both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this genesis restore was being used on a zero height restart, then that might result in it taking a really long time to send out a distribution... not sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. A zero height restart could take a problematic long time to distribute due to this line:
interchain-security/x/ccv/consumer/keeper/distribution.go
Line 58 in b10e132
Actually
LastTransmissionBlockHeight
should never be greater than the current block height.