Skip to content

Commit

Permalink
fix: Fix bug and add test case (#2168)
Browse files Browse the repository at this point in the history
* Fix bug and add test case

* Clean up log messages

* Adjust mock expectations

* Fix integration tests

* Adjust info to debug; return err instead of panicking
  • Loading branch information
p-offtermatt authored Aug 23, 2024
1 parent 5028765 commit 3a0c55f
Show file tree
Hide file tree
Showing 17 changed files with 348 additions and 87 deletions.
166 changes: 152 additions & 14 deletions tests/e2e/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,21 @@ type (
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 @@ func GetTestConfig(cfgType TestConfigType, providerVersion, consumerVersion stri
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 @@ func InactiveProviderValsTestConfig() TestConfig {
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
}

return tr
}

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

Expand Down Expand Up @@ -1274,3 +1296,119 @@ func GetHermesConfig(hermesVersion, queryNodeIP string, chainCfg ChainConfig, is
}
return hermesConfig
}

// GetExtraValidatorConfigs returns a map of extra validator configurations.
// These are configurations that are not part of the default configurations,
// for cases where more validators are needed.
// Commented out fields are fields that can be set, but are not necessary for the test
// they are used in so far.
// These are left as guidance to fill out as they become relevant in the future.
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,
},
},
},
},
}
}
13 changes: 12 additions & 1 deletion tests/integration/partial_set_security_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package integration

import (
"slices"
"sort"
"testing"

"cosmossdk.io/math"
Expand Down Expand Up @@ -119,9 +120,19 @@ func TestMinStake(t *testing.T) {
lastVals, err := providerKeeper.GetLastBondedValidators(s.providerChain.GetContext())
s.Require().NoError(err)

// Assuming tc.stakedTokens is defined somewhere in your test case
// Create a copy of the tc.stakedTokens slice
sortedTokens := make([]int64, len(tc.stakedTokens))
copy(sortedTokens, tc.stakedTokens)

// Sort the copied slice in descending order
sort.Slice(sortedTokens, func(i, j int) bool {
return sortedTokens[i] > sortedTokens[j]
})

for i, val := range lastVals {
// check that the initial state was set correctly
require.Equal(s.T(), math.NewInt(tc.stakedTokens[i]), val.Tokens)
require.Equal(s.T(), math.NewInt(sortedTokens[i]), val.Tokens)
}

// check the validator set on the consumer chain is the original one
Expand Down
Loading

0 comments on commit 3a0c55f

Please sign in to comment.