Skip to content

Commit

Permalink
Add test for inactive vals with top N
Browse files Browse the repository at this point in the history
  • Loading branch information
p-offtermatt committed Jul 19, 2024
1 parent 4caa577 commit 44c2364
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
9 changes: 9 additions & 0 deletions docs/docs/adrs/adr-017-allowing-inactive-validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ The validator should be neither slashed nor jailed for downtime.
This can be tested by having an inactive validator go offline on a consumer chain for long enough to accrue downtime.
The consumer chain should send a SlashPacket to the provider chain, which should jail the validator.

### Scenario 6: Inactive validators should not be counted when computing the minimum power in the top N

This can be tested like this:
* Start a provider chain with validator powers alice=300, bob=200, charlie=100 and 2 max provider consensus validators
* So alice and bob will validate on the provider
* Start a consumer chain with top N = 51%.
* Without inactive validators, this means both alice and bob have to validate. But since charlie is inactive, this means bob is *not* in the top N
* Verify that alice is in the top N, but bob is not

* **Mint**:

## Consequences
Expand Down
6 changes: 6 additions & 0 deletions tests/e2e/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ var stepChoices = map[string]StepChoice{
description: "test inactive validators on consumer",
testConfig: InactiveProviderValsTestCfg,
},
"inactive-vals-topN": {
name: "inactive-vals-topN",
steps: stepsInactiveValsWithTopN(),
description: "test inactive validators on topN chain",
testConfig: InactiveProviderValsTestCfg,
},
}

func getTestCaseUsageString() string {
Expand Down
136 changes: 136 additions & 0 deletions tests/e2e/steps_inactive_vals.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,139 @@ func setupOptInChain() []Step {
},
}
}

func stepsInactiveValsWithTopN() []Step {
return []Step{
{
Action: StartChainAction{
Chain: ChainID("provi"),
Validators: []StartChainValidator{
{Id: ValidatorID("alice"), Stake: 100000000, Allocation: 10000000000},
{Id: ValidatorID("bob"), Stake: 200000000, Allocation: 10000000000},
{Id: ValidatorID("carol"), Stake: 300000000, Allocation: 10000000000},
},
},
State: State{
ChainID("provi"): ChainState{
ValPowers: &map[ValidatorID]uint{
ValidatorID("alice"): 0, // max consensus validators is 2, so alice should not be in power
ValidatorID("bob"): 200,
ValidatorID("carol"): 300,
},
StakedTokens: &map[ValidatorID]uint{
ValidatorID("alice"): 100000000,
ValidatorID("bob"): 200000000,
ValidatorID("carol"): 300000000,
},
Rewards: &Rewards{
IsNativeDenom: true, // check for rewards in the provider denom
IsIncrementalReward: true, // we need to get incremental rewards
// if we would look at total rewards, alice would trivially also get rewards,
// because she gets rewards in the first block due to being in the genesis
IsRewarded: map[ValidatorID]bool{
ValidatorID("alice"): false,
ValidatorID("bob"): true,
ValidatorID("carol"): true,
},
},
},
},
},
{
Action: SubmitConsumerAdditionProposalAction{
Chain: ChainID("provi"),
From: ValidatorID("alice"),
Deposit: 10000001,
ConsumerChain: ChainID("consu"),
SpawnTime: 0,
InitialHeight: clienttypes.Height{RevisionNumber: 0, RevisionHeight: 1},
TopN: 51,
},
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")},
Vote: []string{"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"): {},
ValidatorID("bob"): {}, // bob doesn't have to validate because he is not in the top N
ValidatorID("carol"): {"consu"},
},
},
},
},
{
Action: StartConsumerChainAction{
ConsumerChain: ChainID("consu"),
ProviderChain: ChainID("provi"),
Validators: []StartChainValidator{
{Id: ValidatorID("alice"), Stake: 100000000, Allocation: 10000000000},
{Id: ValidatorID("bob"), Stake: 200000000, Allocation: 10000000000},
{Id: ValidatorID("carol"), Stake: 300000000, 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"): 100,
ValidatorID("bob"): 200,
ValidatorID("carol"): 300,
},
},
},
},
{
Action: AddIbcConnectionAction{
ChainA: ChainID("consu"),
ChainB: ChainID("provi"),
ClientA: 0,
ClientB: 0,
},
State: State{},
},
{
Action: AddIbcChannelAction{
ChainA: ChainID("consu"),
ChainB: ChainID("provi"),
ConnectionA: 0,
PortA: "consumer",
PortB: "provider",
Order: "ordered",
},
State: State{},
},
}
}

0 comments on commit 44c2364

Please sign in to comment.