-
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
Onchain upgrade to consumer chain from sovereign chain #697
Onchain upgrade to consumer chain from sovereign chain #697
Conversation
…nsumer chain upgrade height
storeUpgrades := store.StoreUpgrades{} | ||
storeUpgrades := store.StoreUpgrades{ | ||
Added: []string{ibcconsumertypes.ModuleName}, | ||
} | ||
|
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 IsSkipHeight(upgradeInfo.Height) {
return
}
if err != nil { | ||
panic(err) | ||
} | ||
_, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr) |
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.
why not check err and panic here ?
_, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) | ||
if err != nil { | ||
log.Fatal(err) | ||
} |
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.
Hi, about store iterator, please check this issue in gaia, cosmos/gaia#1924
please let me know your opinion.
Hi @jstr1121, thanks again for your code! We've merged a lot of PRs over the past few weeks, so it looks like this branch needs to catch up to main. Let's eventually work together on making an ADR for the implementation of this feature. It would also be useful to setup a 30-60 minute code walkthrough of how the implementation works, and why certain design decisions were made. Would sometime next week work for you? Let's chat on slack |
Will get the conflict fixed soon - I am fine for 30-60 mins call this week, we can schedule a time on slack. |
…o jstr/onchain_upgrade_to_consumer_chain_840
…merge conflict fix issue
Co-authored-by: yaruwangway <[email protected]>
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.
Great stuff!
@@ -506,6 +509,8 @@ func New( | |||
distrtypes.ModuleName, | |||
slashingtypes.ModuleName, | |||
evidencetypes.ModuleName, | |||
consumertypes.ModuleName, // Note: consumer beginblocker before staking module |
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.
I think changes like this would need to be upstreamed to all consumer chains that pattern match this file. No action item for the Stride team, just commenting for awareness on our team
@@ -334,6 +334,7 @@ func New( | |||
&app.IBCKeeper.PortKeeper, | |||
app.IBCKeeper.ConnectionKeeper, | |||
app.IBCKeeper.ClientKeeper, | |||
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.
See
func (k Keeper) mustValidateFields() { |
isDemocConsumer
to make things very clear
tests/sovereign_consumer_upgrade_local/hermes-0.15.0-old-connection/start_provider.sh
Show resolved
Hide resolved
return false | ||
} | ||
|
||
func (k Keeper) SetPreCCV(ctx sdk.Context, state *types.GenesisState) { |
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.
We usually make quick unit tests for CRUD operations like these, especially because this method is not just setting a flag
panic("unimplemented on CCV keeper") | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { | ||
if k.stakingKeeper == nil { | ||
panic("empty staking keeper") |
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.
Should we panic or return in cases like this?
} | ||
|
||
return k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr) | ||
} | ||
return stakingtypes.Validator{} | ||
} |
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.
nit: it'd be cleaner to pass a stakingtypes.InfractionEmpty
infraction type here.
if k.stakingKeeper == nil { | ||
return | ||
} | ||
|
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.
This error message is hard to understand without context imo.
@@ -344,7 +345,7 @@ func New( | |||
|
|||
// register slashing module Slashing hooks to the consumer keeper | |||
app.ConsumerKeeper = *app.ConsumerKeeper.SetHooks(app.SlashingKeeper.Hooks()) | |||
consumerModule := ibcconsumer.NewAppModule(app.ConsumerKeeper) | |||
consumerModule := ibcconsumer.NewAppModule(app.ConsumerKeeper, 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.
Could use a comment here
|
||
if state.PreCCV { | ||
return []abci.ValidatorUpdate{} |
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.
Could use comment that ccv module shouldn't be doing anything yet because staking keeper is still active
func (k Keeper) IterateValidators(sdk.Context, func(index int64, validator stakingtypes.ValidatorI) (stop bool)) { | ||
// IterateValidators iterate democracy staking validators when the block height is before the last sovereign height | ||
func (k Keeper) IterateValidators(ctx sdk.Context, f func(index int64, validator stakingtypes.ValidatorI) (stop bool)) { | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
Could use comment on what edge case this covers
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.
The idea is that all the calls to the staking module are directed to the consumer CCV module as it plays the role of the staking module, even though until the chain fully transitions to be a consumer chain the staking module should be the original staking module.
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.
So basically, once the consumer CCV module is added, the democracy-staking module is also added. In the first block after the upgrade, the democracy-staking acts exactly as the original staking module as the preCCV flag is set (see democracy/staking/module.go). In the EndBlock of the first block, the preCCV flag is unset, which means that the democracy-staking module stops sending updates to TM and the consumer CCV module starts sending these updates.
However, the provider validators are producing blocks two heights later due to the +1 delay of TM (see ABCI spec). Thus, all the conditions for this edge case are wrong.
} | ||
|
||
// IsJailed returns the outstanding slashing flag for the given validator adddress | ||
func (k Keeper) IsValidatorJailed(ctx sdk.Context, addr sdk.ConsAddress) bool { | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
Same here on edge case comment
@@ -89,16 +108,32 @@ func (k Keeper) ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.V | |||
Also, the slashing module will cal lthis function when it observes downtime. In that case | |||
the only requirement on the returned value is that it isn't null. | |||
*/ | |||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
same
if infraction == stakingtypes.InfractionEmpty { | ||
return | ||
} | ||
|
||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
same, maybe we just make this a func to be more readable
I'm having trouble finding the section of code this is located at |
// populate cross chain validators states with initial valset | ||
am.keeper.ApplyCCValidatorChanges(ctx, initialValSet) | ||
|
||
initialSetFlag := make(map[string]bool) |
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.
@smarshall-spitzbart please add a comment here explaining the logic.
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.
I'll add "Add validator updates to initialValSet, such that the "old" validators returned from GetLastValidators are given zero power, and the "new" validators are given their full power."
if infraction == stakingtypes.InfractionEmpty { | ||
return | ||
} | ||
|
||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
Can never be the case that ctx.BlockHeight() < k.LastSovereignHeight(ctx)
as the CCV module was not on the chain.
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.
This is not the correct way to deal with slashing. This slash request could be for one of the following cases:
- An infraction committed by a sovereign chain validator. This can be detected via the infraction height. The sovereign chain validator set is active until the height
h
(inclusive). Note thath != LastSovereignHeight
.LastSovereignHeight
is the height the provider validator set was sent to TM. According to the ABCI spec,h = LastSovereignHeight + 1
. In this case, the validator should be slashed if the unbonding period didn't pass yet. Still need to implement a way in democracy-staking that not slash validators after unbonding period elapsed after the switch. - An infraction committed by a provider validator. Again, the infraction height can be used for detection.
return AppModule{ | ||
keeper: k, | ||
sk: sk, |
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.
Why do we need this? The DemocracyStakingKeeper can be access via am.keeper.stakingKeeper
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.
This has to do with the capabilities model, am.keeper.stakingKeeper
is non-exported and not accessible.
@@ -506,6 +509,8 @@ func New( | |||
distrtypes.ModuleName, | |||
slashingtypes.ModuleName, | |||
evidencetypes.ModuleName, | |||
consumertypes.ModuleName, // Note: consumer beginblocker before staking module |
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.
@jstr1121 Why is this order necessary?
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.
Beginblocker order shouldn't matter AFAIK
) | ||
app.MM.SetOrderEndBlockers( | ||
crisistypes.ModuleName, | ||
govtypes.ModuleName, | ||
consumertypes.ModuleName, // Note: consumer endblocker before staking module |
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.
@jstr1121 Why is this order necessary?
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.
With 1269163, the order doesn't matter AFAIK
@@ -550,6 +554,7 @@ func New( | |||
capabilitytypes.ModuleName, | |||
authtypes.ModuleName, | |||
banktypes.ModuleName, | |||
consumertypes.ModuleName, // Note: consumer initiation before staking module |
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.
@jstr1121 Why is this order necessary?
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.
Same here, InitGenesis shouldn't matter unless I'm missing something
// TODO: should have a way to read from current node home | ||
userHomeDir, err := os.UserHomeDir() | ||
if err != nil { | ||
stdlog.Println("Failed to get home dir %2", err) | ||
} | ||
nodeHome := userHomeDir + "/.sovereign/config/genesis.json" | ||
appState, _, err := genutiltypes.GenesisStateFromGenFile(nodeHome) | ||
if err != nil { | ||
return fromVM, fmt.Errorf("failed to unmarshal genesis state: %w", err) | ||
} | ||
|
||
var consumerGenesis = consumertypes.GenesisState{} | ||
appCodec.MustUnmarshalJSON(appState[consumertypes.ModuleName], &consumerGenesis) | ||
|
||
consumerGenesis.PreCCV = true | ||
app.ConsumerKeeper.InitGenesis(ctx, &consumerGenesis) | ||
|
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.
This is needed only because the provider doesn't create a correct init genesis for the consumer CCV module with preCCV
set to true
. See the spec for more details. @smarshall-spitzbart please open an issue to address this.
storeUpgrades := store.StoreUpgrades{ | ||
Added: []string{consumertypes.ModuleName}, | ||
} | ||
|
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.
@jstr1121 What are these changes for?
@@ -0,0 +1,808 @@ | |||
package app |
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.
Why do we need to have the app.go for the sovereign chain in this repo?
// PreCCV is true when consumer chain used to be running on non-consumer chain, and when it is in the progress of upgrading | ||
// to consumer chain, where consumer chain upgrade is done. | ||
if state.PreCCV { | ||
k.SetPreCCV(ctx, state) |
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.
@smarshall-spitzbart please store the init val set explicitly.
func (k Keeper) Jail(ctx sdk.Context, addr sdk.ConsAddress) {} | ||
// Jail performs jail operation on democracy staking validator if block height after last sovereign height | ||
func (k Keeper) Jail(ctx sdk.Context, addr sdk.ConsAddress) { | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
ditto: see comments from Slash
|
||
// Unjail performs unjail operation on democracy staking validator if block height after last sovereign height | ||
func (k Keeper) Unjail(ctx sdk.Context, addr sdk.ConsAddress) { | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
ditto: see comments from Slash
panic("unimplemented on CCV keeper") | ||
// MaxValidators returns max number of validators on democracy staking if block height after last sovereign height | ||
func (k Keeper) MaxValidators(ctx sdk.Context) uint32 { | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
ditto
func (k Keeper) Unjail(sdk.Context, sdk.ConsAddress) {} | ||
// Delegation returns delegation from an address to a democracy staking validator if block height after last sovereign height | ||
func (k Keeper) Delegation(ctx sdk.Context, addr sdk.AccAddress, valAddr sdk.ValAddress) stakingtypes.DelegationI { | ||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
ditto
@@ -89,16 +108,32 @@ func (k Keeper) ValidatorByConsAddr(sdk.Context, sdk.ConsAddress) stakingtypes.V | |||
Also, the slashing module will cal lthis function when it observes downtime. In that case | |||
the only requirement on the returned value is that it isn't null. | |||
*/ | |||
if k.IsPreCCV(ctx) || ctx.BlockHeight() <= k.LastSovereignHeight(ctx) { |
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.
ditto
Description
This PR is supposed to upgrade intechain-security module for on-chain upgrade from sovereign to consumer chain.
Applying the changes mentioned in cosmos/ibc#840
Changes
Type of change
If you've checked more than one of the first three boxes, consider splitting this PR into multiple PRs!
Feature
: Changes and/or adds code behavior, irrelevant to bug fixesFix
: Changes and/or adds code behavior, specifically to fix a bugRefactor
: Changes existing code style, naming, structure, etc.Testing
: Adds testingDocs
: Adds documentationRegression tests
If
Refactor
, describe the new or existing tests that verify no behavior was changed or added where refactors were introduced.New behavior tests
If
Feature
orFix
, describe the new or existing tests that verify the new behavior is correct and expected.