From 89aad1c00543f72479e9a236024fa4b6c1666173 Mon Sep 17 00:00:00 2001 From: Philip Offtermatt Date: Fri, 19 Jul 2024 10:27:52 +0200 Subject: [PATCH] Add property-based test for inactive vals --- .../keeper/partial_set_security_test.go | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/x/ccv/provider/keeper/partial_set_security_test.go b/x/ccv/provider/keeper/partial_set_security_test.go index 8e415b30d7..e015af850d 100644 --- a/x/ccv/provider/keeper/partial_set_security_test.go +++ b/x/ccv/provider/keeper/partial_set_security_test.go @@ -820,3 +820,57 @@ func TestMaxValidatorRank(t *testing.T) { }) } } + +// TestMaxProviderConsensusValidators checks that the number of validators in the next validator set is at most +// the maxProviderConsensusValidators parameter if the consumer chain does not allow inactive validators to validate. +func TestIfInactiveValsDisallowedProperty(t *testing.T) { + rapid.Check(t, func(r *rapid.T) { + providerKeeper, ctx, ctrl, mocks := testkeeper.GetProviderKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t)) + defer ctrl.Finish() + + // Generate a random number of validators with random powers + valPowers := rapid.SliceOfN(rapid.Int64Range(1, 100), 1, 100).Draw(r, "valPowers") + vals, consAddrs := createStakingValidatorsAndMocks(ctx, mocks, valPowers...) + + // opt the validators in + for _, valAddr := range consAddrs { + providerKeeper.SetOptedIn(ctx, "chainID", valAddr) + } + + // Randomly choose values for parameters + minStake := rapid.Uint64Range(0, 101).Draw(r, "minStake") + maxRank := rapid.Uint32Range(0, 11).Draw(r, "maxRank") + maxProviderConsensusVals := rapid.Uint32Range(1, 11).Draw(r, "maxProviderConsensusVals") + + // Set up the parameters in the provider keeper + providerKeeper.SetAllowInactiveValidators(ctx, "chainID", false) // do not allow inactive validators + providerKeeper.SetMinStake(ctx, "chainID", minStake) + providerKeeper.SetMaxValidatorRank(ctx, "chainID", maxRank) + params := providerKeeper.GetParams(ctx) + params.MaxProviderConsensusValidators = int64(maxProviderConsensusVals) + providerKeeper.SetParams(ctx, params) + + // Compute the next validators + nextVals := providerKeeper.ComputeNextValidators(ctx, "chainID", vals) + + // Check that the length of nextVals is at most maxProviderConsensusVals + require.LessOrEqual(t, len(nextVals), int(maxProviderConsensusVals), "The length of nextVals should be at most maxProviderConsensusVals") + + // Sanity check: we only get 0 next validators if either: + // - maxProviderConsensusVals is 0 + // - the maximal validator power is less than the min stake + if len(nextVals) == 0 { + maxValPower := int64(0) + for _, power := range valPowers { + if power > maxValPower { + maxValPower = power + } + } + require.True( + t, + maxProviderConsensusVals == 0 || maxValPower < int64(minStake), + "The length of nextVals should only be 0 if either maxProviderConsensusVals is 0 or the maximal validator power is less than the min stake", + ) + } + }) +}