Skip to content

Commit

Permalink
Start adding an extension to the simulator
Browse files Browse the repository at this point in the history
  • Loading branch information
p-offtermatt committed Jul 22, 2024
1 parent 1b40c17 commit e7978b4
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 5 deletions.
31 changes: 28 additions & 3 deletions .github/workflows/simulation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ concurrency:
cancel-in-progress: true

jobs:
simulation:
full:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -38,7 +38,32 @@ jobs:
**/go.sum
**/Makefile
Makefile
- name: simulation test
- name: full simulation test
if: env.GIT_DIFF
run: |
make sim-full
make sim-full
no-inactive:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
check-latest: true
cache: true
cache-dependency-path: go.sum
- uses: technote-space/[email protected]
id: git_diff
with:
PATTERNS: |
**/*.go
go.mod
go.sum
**/go.mod
**/go.sum
**/Makefile
Makefile
- name: simulation test without inactive validators
if: env.GIT_DIFF
run: |
make sim-full-no-inactive-vals
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,13 @@ verify-models:
# Run a full simulation test
sim-full:
cd app/provider;\
go test -mod=readonly -run=^TestFullAppSimulation$ -Enabled=true -NumBlocks=500 -BlockSize=200 -Commit=true -timeout 24h github.com/cosmos/interchain-security/v5/app/provider -v
go test -mod=readonly . -run=^TestFullAppSimulation$ -Enabled=true -NumBlocks=500 -BlockSize=200 -Commit=true -timeout 24h -v

# Run full simulation without any inactive validators
sim-full-no-inactive-vals:
cd app/provider;\
go test -mod=readonly . -run=^TestFullAppSimulation$ -Enabled=true -NumBlocks=500 -BlockSize=200 -Commit=true -timeout 24h -Params=no_inactive_vals_params.json -v


###############################################################################
### Linting ###
Expand Down
4 changes: 4 additions & 0 deletions app/provider/no_inactive_vals_params.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"max_validators": 100,
"max_provider_consensus_validators": 100
}
5 changes: 5 additions & 0 deletions app/provider/sim_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app_test

import (
"fmt"
"os"
"testing"

Expand Down Expand Up @@ -39,6 +40,10 @@ func TestFullAppSimulation(t *testing.T) {
config := simcli.NewConfigFromFlags()
config.ChainID = "provi"

fmt.Println("========================================")
fmt.Println(config)
fmt.Println("========================================")

db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "leveldb-app-sim", "Simulation", simcli.FlagVerboseValue, simcli.FlagEnabledValue)
if skip {
t.Skip("skipping application simulation")
Expand Down
111 changes: 111 additions & 0 deletions x/ccv/provider/keeper/invariants.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
types "github.com/cosmos/interchain-security/v5/x/ccv/provider/types"
)

// RegisterInvariants registers all staking invariants
func RegisterInvariants(ir sdk.InvariantRegistry, k *Keeper) {
ir.RegisterRoute(types.ModuleName, "max-provider-validators",
MaxProviderConsensusValidatorsInvariant(k))

ir.RegisterRoute(types.ModuleName, "staking-keeper-equivalence",
StakingKeeperEquivalenceInvariant(*k))
}

// MaxProviderConsensusValidatorsInvariant checks that the number of provider consensus validators
Expand All @@ -30,3 +34,110 @@ func MaxProviderConsensusValidatorsInvariant(k *Keeper) sdk.Invariant {
return "", false
}
}

// StakingKeeperEquivalenceInvariant checks that *if* MaxProviderConsensusValidators == MaxValidators, then
// the staking keeper and the provider keeper
// return the same values for their common interface,
// i.e. the functions from staking_keeper_interface.go
func StakingKeeperEquivalenceInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
stakingKeeper := k.stakingKeeper

maxValidators, err := stakingKeeper.MaxValidators(ctx)
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting max validators from staking keeper: %v", err)), true
}

maxProviderConsensusValidators := k.GetParams(ctx).MaxProviderConsensusValidators

fmt.Println(k.GetParams(ctx))

if maxValidators != uint32(maxProviderConsensusValidators) {
// the invariant should only check something if these two numbers are equal,
// so skip in this case
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("maxValidators: %v, maxProviderVals: %v", maxValidators, maxProviderConsensusValidators)), true
}

// check that the staking keeper and the provider keeper return the same values
// for the common interface functions

// Check IterateBondedValidatorsByPower
providerBondedValidators := make([]stakingtypes.Validator, 0)
err = k.IterateBondedValidatorsByPower(ctx, func(index int64, validator stakingtypes.ValidatorI) (stop bool) {
providerBondedValidators = append(providerBondedValidators, validator.(stakingtypes.Validator))
return false
})
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting provider bonded validators: %v", err)), true
}

stakingBondedValidators := make([]stakingtypes.Validator, 0)
err = stakingKeeper.IterateBondedValidatorsByPower(ctx, func(index int64, validator stakingtypes.ValidatorI) (stop bool) {
stakingBondedValidators = append(stakingBondedValidators, validator.(stakingtypes.Validator))
return false
})
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting staking bonded validators: %v", err)), true
}

if len(providerBondedValidators) != len(stakingBondedValidators) {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("provider bonded validators: %v, staking bonded validators: %v",
providerBondedValidators, stakingBondedValidators)), true
}

for i, providerVal := range providerBondedValidators {
stakingVal := stakingBondedValidators[i]

if providerVal.Equal(&stakingVal) {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("provider validator: %v, staking validator: %v",
providerVal.GetOperator(), stakingVal.GetOperator())), true
}
}

// Check TotalBondedTokens
providerTotalBondedTokens, err := k.TotalBondedTokens(ctx)
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting provider total bonded tokens: %v", err)), true
}

stakingTotalBondedTokens, err := stakingKeeper.TotalBondedTokens(ctx)
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting staking total bonded tokens: %v", err)), true
}

if !providerTotalBondedTokens.Equal(stakingTotalBondedTokens) {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("provider total bonded tokens: %v, staking total bonded tokens: %v",
providerTotalBondedTokens, stakingTotalBondedTokens)), true
}

// Check BondedRatio
providerBondedRatio, err := k.BondedRatio(ctx)
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting provider bonded ratio: %v", err)), true
}

stakingBondedRatio, err := stakingKeeper.BondedRatio(ctx)
if err != nil {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("error getting staking bonded ratio: %v", err)), true
}

if !providerBondedRatio.Equal(stakingBondedRatio) {
return sdk.FormatInvariant(types.ModuleName, "staking-keeper-equivalence",
fmt.Sprintf("provider bonded ratio: %v, staking bonded ratio: %v",
providerBondedRatio, stakingBondedRatio)), true
}

return "", false
}
}
2 changes: 1 addition & 1 deletion x/ccv/provider/keeper/staking_keeper_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (k Keeper) TotalBondedTokens(ctx context.Context) (math.Int, error) {
return false
})

return totalBondedTokens, nil
return totalBondedTokens.Sub(math.NewInt(100)), nil
}

// IterateDelegations is the same as IterateDelegations in the StakingKeeper.
Expand Down
1 change: 1 addition & 0 deletions x/ccv/provider/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {

// RegisterStoreDecoder registers a decoder for provider module's types
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
// TODO: implement?
}

// WeightedOperations returns the all the provider module operations with their respective weights.
Expand Down
15 changes: 15 additions & 0 deletions x/ccv/provider/simulation/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package simulation

import (
"github.com/cosmos/cosmos-sdk/types/kv"
"github.com/gogo/protobuf/codec"
)

// NewDecodeStore returns a decoder function closure that umarshals the KVPair's
// Value to the corresponding authz type.
func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string {
return func(kvA, kvB kv.Pair) string {
panic("TO BE IMPLEMENTED")
return ""
}
}

0 comments on commit e7978b4

Please sign in to comment.