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

fix: Fix bug and add test case #2168

Merged
merged 5 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
160 changes: 146 additions & 14 deletions tests/e2e/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,21 @@
type TestConfigType string

const (
DefaultTestCfg TestConfigType = "default"
ChangeoverTestCfg TestConfigType = "changeover"
DemocracyTestCfg TestConfigType = "democracy"
DemocracyRewardTestCfg TestConfigType = "democracy-reward"
SlashThrottleTestCfg TestConfigType = "slash-throttling"
MulticonsumerTestCfg TestConfigType = "multi-consumer"
ConsumerMisbehaviourTestCfg TestConfigType = "consumer-misbehaviour"
CompatibilityTestCfg TestConfigType = "compatibility"
SmallMaxValidatorsTestCfg TestConfigType = "small-max-validators"
InactiveProviderValsTestCfg TestConfigType = "inactive-provider-vals"
GovTestCfg TestConfigType = "gov"
InactiveValsGovTestCfg TestConfigType = "inactive-vals-gov"
InactiveValsMintTestCfg TestConfigType = "inactive-vals-mint"
MintTestCfg TestConfigType = "mint"
DefaultTestCfg TestConfigType = "default"
ChangeoverTestCfg TestConfigType = "changeover"
DemocracyTestCfg TestConfigType = "democracy"
DemocracyRewardTestCfg TestConfigType = "democracy-reward"
SlashThrottleTestCfg TestConfigType = "slash-throttling"
MulticonsumerTestCfg TestConfigType = "multi-consumer"
ConsumerMisbehaviourTestCfg TestConfigType = "consumer-misbehaviour"
CompatibilityTestCfg TestConfigType = "compatibility"
SmallMaxValidatorsTestCfg TestConfigType = "small-max-validators"
InactiveProviderValsTestCfg TestConfigType = "inactive-provider-vals"
GovTestCfg TestConfigType = "gov"
InactiveValsGovTestCfg TestConfigType = "inactive-vals-gov"
InactiveValsMintTestCfg TestConfigType = "inactive-vals-mint"
MintTestCfg TestConfigType = "mint"
InactiveValsExtraValsTestCfg TestConfigType = "inactive-vals-extra-vals"
)

type TestConfig struct {
Expand Down Expand Up @@ -205,6 +206,8 @@
testCfg = InactiveValsMintTestConfig()
case MintTestCfg:
testCfg = MintTestConfig()
case InactiveValsExtraValsTestCfg:
testCfg = InactiveValsExtraValsTestConfig()
default:
panic(fmt.Sprintf("Invalid test config: %s", cfgType))
}
Expand Down Expand Up @@ -610,6 +613,25 @@
return tr
}

func InactiveValsExtraValsTestConfig() TestConfig {
tr := InactiveProviderValsTestConfig()

// set the MaxProviderConsensusValidators param to 4
proviConfig := tr.chainConfigs[ChainID("provi")]
proviConfig.GenesisChanges += " | .app_state.provider.params.max_provider_consensus_validators = \"4\""
// set max validators to 5
proviConfig.GenesisChanges += " | .app_state.staking.params.max_validators = \"5\""
tr.chainConfigs[ChainID("provi")] = proviConfig

// add the extra validators to the validator config
extraVals := GetExtraValidatorConfigs()
for valId, val := range extraVals {
tr.validatorConfigs[valId] = val
}
Comment on lines +628 to +630

Check warning

Code scanning / CodeQL

Iteration over map Warning test

Iteration over map may be a possible source of non-determinism

return tr
}

func SmallMaxValidatorsTestConfig() TestConfig {
cfg := DefaultTestConfig()

Expand Down Expand Up @@ -1274,3 +1296,113 @@
}
return hermesConfig
}

func GetExtraValidatorConfigs() map[ValidatorID]ValidatorConfig {
return map[ValidatorID]ValidatorConfig{
ValidatorID("david"): {
Mnemonic: "save arm pill nothing riot park analyst fever couple use reform hotel involve captain ride spell cricket spoil admit proud file renew below add",
DelAddress: "cosmos1jv9j37zakskecthedez2xuvkd7aj4v96u6wm57",
// DelAddressOnConsumer: "consumer1dkas8mu4kyhl5jrh4nzvm65qz588hy9qahzgv6",
ValoperAddress: "cosmosvaloper1jv9j37zakskecthedez2xuvkd7aj4v96ew6wcd",
// ValoperAddressOnConsumer: "consumervaloper1dkas8mu4kyhl5jrh4nzvm65qz588hy9qj0phzw",
ValconsAddress: "cosmosvalcons1vde2tkme0336durkp7qlehyw2v0r2rgm5lfcw5",
ValconsAddressOnConsumer: "consumervalcons1vde2tkme0336durkp7qlehyw2v0r2rgmmxnal5",
PrivValidatorKey: `{
"address": "6372A5DB797C63A6F0760F81FCDC8E531E350D1B",
"pub_key": {
"type": "tendermint/PubKeyEd25519",
"value": "JFt8aKr1AnubC23rVEUza0pl3DQC0VdC6jUlnkjCh5o="
},
"priv_key": {
"type": "tendermint/PrivKeyEd25519",
"value": "mBErI1aFTt2VHNiWkb14mEfSIfUU6PHndJCKaJ2XjkwkW3xoqvUCe5sLbetURTNrSmXcNALRV0LqNSWeSMKHmg=="
}
}`,
NodeKey: `{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"LJQ/VDAYtEEaJC3NA32fZ2oLLm9akLeLVnBlJ2WOYEMLohbwfac0x42Qh23E/ByEMliSjfGvLFQZIYzRqwJcLA=="}}`,
IpSuffix: "7",

// // consumer chain assigned key
// ConsumerMnemonic: "grunt list hour endless observe better spoil penalty lab duck only layer vague fantasy satoshi record demise topple space shaft solar practice donor sphere",
// ConsumerDelAddress: "consumer1q90l6j6lzzgt460ehjj56azknlt5yrd44y2uke",
// ConsumerDelAddressOnProvider: "cosmos1q90l6j6lzzgt460ehjj56azknlt5yrd4s38n97",
// ConsumerValoperAddress: "consumervaloper1q90l6j6lzzgt460ehjj56azknlt5yrd46ufrcd",
// ConsumerValoperAddressOnProvider: "cosmosvaloper1q90l6j6lzzgt460ehjj56azknlt5yrd449nxfd",
// ConsumerValconsAddress: "consumervalcons1uuec3cjxajv5te08p220usrjhkfhg9wyref26m",
// ConsumerValconsAddressOnProvider: "cosmosvalcons1uuec3cjxajv5te08p220usrjhkfhg9wyvqn0tm",
// ConsumerValPubKey: `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"QlG+iYe6AyYpvY1z9RNJKCVlH14Q/qSz4EjGdGCru3o="}`,
// ConsumerPrivValidatorKey: `{"address":"E73388E246EC9945E5E70A94FE4072BD937415C4","pub_key":{"type":"tendermint/PubKeyEd25519","value":"QlG+iYe6AyYpvY1z9RNJKCVlH14Q/qSz4EjGdGCru3o="},"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"OFR4w+FC6EMw5fAGTrHVexyPrjzQ7QfqgZOMgVf0izlCUb6Jh7oDJim9jXP1E0koJWUfXhD+pLPgSMZ0YKu7eg=="}}`,
// ConsumerNodeKey: `{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"uhPCqnL2KE8m/8OFNLQ5bN3CJr6mds+xfBi0E4umT/s2uWiJhet+vbYx88DHSdof3gGFNTIzAIxSppscBKX96w=="}}`,
// UseConsumerKey: false,
},
ValidatorID("eve"): {
Mnemonic: "board lava muffin daughter frozen chimney chest whale give subject inquiry forward alter gasp busy flee wire ecology invite code comic cloth shoot pen",
DelAddress: "cosmos1p56m290cgys4396e3f8p4kj9lrzwak7zemg45t",
// DelAddressOnConsumer: "consumer1dkas8mu4kyhl5jrh4nzvm65qz588hy9qahzgv6",
ValoperAddress: "cosmosvaloper1p56m290cgys4396e3f8p4kj9lrzwak7zu0uqcc",
// ValoperAddressOnConsumer: "consumervaloper1dkas8mu4kyhl5jrh4nzvm65qz588hy9qj0phzw",
ValconsAddress: "cosmosvalcons1dqvy6lz440hj4zxjske5knsyx60ac5estqx6k2",
ValconsAddressOnConsumer: "consumervalcons1dqvy6lz440hj4zxjske5knsyx60ac5esyeul82",
PrivValidatorKey: `{
"address": "68184D7C55ABEF2A88D285B34B4E04369FDC5330",
"pub_key": {
"type": "tendermint/PubKeyEd25519",
"value": "QbLLxm/mNHfS9WWXTxvt30D2xeC7/HRrMrZJIVOtj9s="
},
"priv_key": {
"type": "tendermint/PrivKeyEd25519",
"value": "LDPp4B9/Q18yZBJv2zXMnCA+NB9wvaM3XAkWLuCvbaFBssvGb+Y0d9L1ZZdPG+3fQPbF4Lv8dGsytkkhU62P2w=="
}
}`,
NodeKey: `{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"eyDlEXWWP5KwD2IKZeJ/bvf8jT+pVsXYVjpV2HfP+GEjngJe2dNbuuNqtC6L7SFcp5/W2aOIKsslASqv+Oai9Q=="}}`,
IpSuffix: "8",

// // consumer chain assigned key
// ConsumerMnemonic: "grunt list hour endless observe better spoil penalty lab duck only layer vague fantasy satoshi record demise topple space shaft solar practice donor sphere",
// ConsumerDelAddress: "consumer1q90l6j6lzzgt460ehjj56azknlt5yrd44y2uke",
// ConsumerDelAddressOnProvider: "cosmos1q90l6j6lzzgt460ehjj56azknlt5yrd4s38n97",
// ConsumerValoperAddress: "consumervaloper1q90l6j6lzzgt460ehjj56azknlt5yrd46ufrcd",
// ConsumerValoperAddressOnProvider: "cosmosvaloper1q90l6j6lzzgt460ehjj56azknlt5yrd449nxfd",
// ConsumerValconsAddress: "consumervalcons1uuec3cjxajv5te08p220usrjhkfhg9wyref26m",
// ConsumerValconsAddressOnProvider: "cosmosvalcons1uuec3cjxajv5te08p220usrjhkfhg9wyvqn0tm",
// ConsumerValPubKey: `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"QlG+iYe6AyYpvY1z9RNJKCVlH14Q/qSz4EjGdGCru3o="}`,
// ConsumerPrivValidatorKey: `{"address":"E73388E246EC9945E5E70A94FE4072BD937415C4","pub_key":{"type":"tendermint/PubKeyEd25519","value":"QlG+iYe6AyYpvY1z9RNJKCVlH14Q/qSz4EjGdGCru3o="},"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"OFR4w+FC6EMw5fAGTrHVexyPrjzQ7QfqgZOMgVf0izlCUb6Jh7oDJim9jXP1E0koJWUfXhD+pLPgSMZ0YKu7eg=="}}`,
// ConsumerNodeKey: `{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"uhPCqnL2KE8m/8OFNLQ5bN3CJr6mds+xfBi0E4umT/s2uWiJhet+vbYx88DHSdof3gGFNTIzAIxSppscBKX96w=="}}`,
// UseConsumerKey: false,
},
ValidatorID("fred"): {
Mnemonic: "squeeze runway ivory cause throw diagram camp cricket clutch lens venture panel explain transfer dove notice nest twist plate van paddle rude summer give",
DelAddress: "cosmos13s90cyesdm2292pn8mnzmjm0ez3nd7jaw32tdq",
// // DelAddressOnConsumer: "consumer1dkas8mu4kyhl5jrh4nzvm65qz588hy9qahzgv6",
ValoperAddress: "cosmosvaloper13s90cyesdm2292pn8mnzmjm0ez3nd7jat977pn",
// // ValoperAddressOnConsumer: "consumervaloper1dkas8mu4kyhl5jrh4nzvm65qz588hy9qj0phzw",
ValconsAddress: "cosmosvalcons1xvuktnaz3rvwmldw7ktv7lcn2xf7l252wmsv5e",
ValconsAddressOnConsumer: "consumervalcons1xvuktnaz3rvwmldw7ktv7lcn2xf7l252pz2f9e",
PrivValidatorKey: `{
"address": "333965CFA288D8EDFDAEF596CF7F135193EFAA8A",
"pub_key": {
"type": "tendermint/PubKeyEd25519",
"value": "nC7g+8/y3NNx7D6Ae970H9954JeqX7SyAxNHh5GnJGs="
},
"priv_key": {
"type": "tendermint/PrivKeyEd25519",
"value": "otxstGMSCO0T4CU/Ouxxaam+HUFoL9ArKmMqvSaaCaCcLuD7z/Lc03HsPoB73vQf33ngl6pftLIDE0eHkackaw=="
}
}`,
NodeKey: `{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"oeJWEaFbLHIgZEbCeVDeYKDqM23fv3j/FobYdhIffQYN2X9MUvBlkhi4Uz6dLQ+vSfZIZb2x2vPcgJsCUpLGnQ=="}}`,
IpSuffix: "9",

// // consumer chain assigned key
// ConsumerMnemonic: "grunt list hour endless observe better spoil penalty lab duck only layer vague fantasy satoshi record demise topple space shaft solar practice donor sphere",
// ConsumerDelAddress: "consumer1q90l6j6lzzgt460ehjj56azknlt5yrd44y2uke",
// ConsumerDelAddressOnProvider: "cosmos1q90l6j6lzzgt460ehjj56azknlt5yrd4s38n97",
// ConsumerValoperAddress: "consumervaloper1q90l6j6lzzgt460ehjj56azknlt5yrd46ufrcd",
// ConsumerValoperAddressOnProvider: "cosmosvaloper1q90l6j6lzzgt460ehjj56azknlt5yrd449nxfd",
// ConsumerValconsAddress: "consumervalcons1uuec3cjxajv5te08p220usrjhkfhg9wyref26m",
// ConsumerValconsAddressOnProvider: "cosmosvalcons1uuec3cjxajv5te08p220usrjhkfhg9wyvqn0tm",
// ConsumerValPubKey: `{"@type":"/cosmos.crypto.ed25519.PubKey","key":"QlG+iYe6AyYpvY1z9RNJKCVlH14Q/qSz4EjGdGCru3o="}`,
// ConsumerPrivValidatorKey: `{"address":"E73388E246EC9945E5E70A94FE4072BD937415C4","pub_key":{"type":"tendermint/PubKeyEd25519","value":"QlG+iYe6AyYpvY1z9RNJKCVlH14Q/qSz4EjGdGCru3o="},"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"OFR4w+FC6EMw5fAGTrHVexyPrjzQ7QfqgZOMgVf0izlCUb6Jh7oDJim9jXP1E0koJWUfXhD+pLPgSMZ0YKu7eg=="}}`,
// ConsumerNodeKey: `{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"uhPCqnL2KE8m/8OFNLQ5bN3CJr6mds+xfBi0E4umT/s2uWiJhet+vbYx88DHSdof3gGFNTIzAIxSppscBKX96w=="}}`,
// UseConsumerKey: false,
},
}
}
6 changes: 6 additions & 0 deletions tests/e2e/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ var stepChoices = map[string]StepChoice{
description: "test minting without inactive validators as a sanity check",
testConfig: MintTestCfg,
},
"inactive-vals-outside-max-validators": {
name: "inactive-vals-outside-max-validators",
steps: stepsInactiveValsTopNReproduce(),
description: "tests the behaviour of inactive validators with a top N = 100 chain and when max_validators is smaller than the total number of validators",
testConfig: InactiveValsExtraValsTestCfg,
},
}

func getTestCaseUsageString() string {
Expand Down
138 changes: 138 additions & 0 deletions tests/e2e/steps.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package main

import (
"strconv"

gov "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types"
)

type Step struct {
Action interface{}
State State
Expand Down Expand Up @@ -138,3 +145,134 @@ var consumerDoubleDowntimeSteps = concatSteps(
stepsRedelegate("consu"),
stepsDoubleDowntime("consu"),
)

func stepsInactiveValsTopNReproduce() []Step {
alice_power := uint(30)
bob_power := uint(29)
carol_power := uint(20)
david_power := uint(10)
eve_power := uint(7)
fred_power := uint(4)

return []Step{
{
Action: StartChainAction{
Chain: ChainID("provi"),
Validators: []StartChainValidator{
{Id: ValidatorID("alice"), Stake: alice_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("bob"), Stake: bob_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("carol"), Stake: carol_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("david"), Stake: david_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("eve"), Stake: eve_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("fred"), Stake: fred_power * 1000000, Allocation: 10000000000},
},
},
State: State{
ChainID("provi"): ChainState{
ValPowers: &map[ValidatorID]uint{
ValidatorID("alice"): alice_power,
ValidatorID("bob"): bob_power,
ValidatorID("carol"): carol_power,
ValidatorID("david"): david_power,
ValidatorID("eve"): 0, // max provider consensus validators is 4, so eve and fred are at 0 power
ValidatorID("fred"): 0,
},
StakedTokens: &map[ValidatorID]uint{
ValidatorID("alice"): alice_power * 1000000,
ValidatorID("bob"): bob_power * 1000000,
ValidatorID("carol"): carol_power * 1000000,
ValidatorID("david"): david_power * 1000000,
ValidatorID("eve"): eve_power * 1000000,
ValidatorID("fred"): fred_power * 1000000,
},
},
},
},
{
Action: SubmitConsumerAdditionProposalAction{
Chain: ChainID("provi"),
From: ValidatorID("alice"),
Deposit: 10000001,
ConsumerChain: ChainID("consu"),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
TopN: 100,
AllowInactiveVals: false,
},
State: State{
ChainID("provi"): ChainState{
Proposals: &map[uint]Proposal{
1: ConsumerAdditionProposal{
Deposit: 10000001,
Chain: ChainID("consu"),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_VOTING_PERIOD)),
},
},
},
},
},
{
Action: VoteGovProposalAction{
Chain: ChainID("provi"),
From: []ValidatorID{ValidatorID("alice"), ValidatorID("bob"), ValidatorID("carol"), ValidatorID("david"), ValidatorID("eve")},
Vote: []string{"yes", "yes", "yes", "yes", "yes"},
PropNumber: 1,
},
State: State{
ChainID("provi"): ChainState{
Proposals: &map[uint]Proposal{
1: ConsumerAdditionProposal{
Deposit: 10000001,
Chain: ChainID("consu"),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
Status: strconv.Itoa(int(gov.ProposalStatus_PROPOSAL_STATUS_PASSED)),
},
},
HasToValidate: &map[ValidatorID][]ChainID{
ValidatorID("alice"): {"consu"},
ValidatorID("bob"): {"consu"},
ValidatorID("carol"): {"consu"},
ValidatorID("david"): {"consu"},
ValidatorID("eve"): {},
ValidatorID("fred"): {},
},
},
},
},
{
Action: StartConsumerChainAction{
ConsumerChain: ChainID("consu"),
ProviderChain: ChainID("provi"),
Validators: []StartChainValidator{
{Id: ValidatorID("alice"), Stake: alice_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("bob"), Stake: bob_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("carol"), Stake: carol_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("david"), Stake: david_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("eve"), Stake: eve_power * 1000000, Allocation: 10000000000},
{Id: ValidatorID("fred"), Stake: fred_power * 1000000, Allocation: 10000000000},
},
// For consumers that're launching with the provider being on an earlier version
// of ICS before the soft opt-out threshold was introduced, we need to set the
// soft opt-out threshold to 0.05 in the consumer genesis to ensure that the
// consumer binary doesn't panic. Sdk requires that all params are set to valid
// values from the genesis file.
GenesisChanges: ".app_state.ccvconsumer.params.soft_opt_out_threshold = \"0.05\"",
},
State: State{
ChainID("consu"): ChainState{
ValPowers: &map[ValidatorID]uint{
ValidatorID("alice"): alice_power,
ValidatorID("bob"): bob_power,
ValidatorID("carol"): carol_power,
ValidatorID("david"): david_power,
ValidatorID("eve"): 0,
ValidatorID("fred"): 0,
},
},
},
},
}
}
17 changes: 16 additions & 1 deletion x/ccv/provider/keeper/partial_set_security.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ func (k Keeper) HandleOptOut(ctx sdk.Context, chainID string, providerAddr types
// OptInTopNValidators opts in to `chainID` all the `bondedValidators` that have at least `minPowerToOptIn` power
func (k Keeper) OptInTopNValidators(ctx sdk.Context, chainID string, bondedValidators []stakingtypes.Validator, minPowerToOptIn int64) {
for _, val := range bondedValidators {
// log the validator
k.Logger(ctx).Info("Opting in validator", "validator", val.GetOperator())

valAddr, err := sdk.ValAddressFromBech32(val.GetOperator())
if err != nil {
k.Logger(ctx).Error("could not retrieve validator address: %s: %s",
Expand All @@ -104,16 +107,28 @@ func (k Keeper) OptInTopNValidators(ctx sdk.Context, chainID string, bondedValid
continue
}
if power >= minPowerToOptIn {
k.Logger(ctx).Info("Before getting cons addr, but power is good",
"validator", val.GetOperator(),
"power", power)
consAddr, err := val.GetConsAddr()
if err != nil {
k.Logger(ctx).Error("could not retrieve validators consensus address: %s: %s",
val, err)
continue
}

k.Logger(ctx).Info("Opting in validator", "validator", val.GetOperator())
p-offtermatt marked this conversation as resolved.
Show resolved Hide resolved

// if validator already exists it gets overwritten
k.SetOptedIn(ctx, chainID, types.NewProviderConsAddress(consAddr))
} // else validators that do not belong to the top N validators but were opted in, remain opted in
} else {
// else validators that do not belong to the top N validators but were opted in, remain opted in
k.Logger(ctx).Info("After getting cons addr, but power is not good",
"validator", val.GetOperator(),
"power", power,
"minPowerToOptIn",
minPowerToOptIn)
}
}
}

Expand Down
Loading
Loading