Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion docs/static/openapi.yml

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions x/action/v1/mocks/expected_keepers_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions x/action/v1/simulation/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,15 @@ func registerSupernode(r *rand.Rand, ctx sdk.Context, k keeper.Keeper, accs []si
continue
}

// Ensure the supernode account is not already associated with another validator.
_, exists, err := k.GetSupernodeKeeper().GetSuperNodeByAccount(ctx, simAccount.Address.String())
if err != nil {
continue
}
if exists {
continue
}

// Check if supernode already exists
_, superNodeExists := k.GetSupernodeKeeper().QuerySuperNode(ctx, valAddr)
if superNodeExists {
Expand Down
1 change: 1 addition & 0 deletions x/action/v1/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type StakingKeeper interface {
type SupernodeKeeper interface {
IsSuperNodeActive(ctx sdk.Context, valAddr sdk.ValAddress) bool
QuerySuperNode(ctx sdk.Context, valOperAddr sdk.ValAddress) (sn sntypes.SuperNode, exists bool)
GetSuperNodeByAccount(ctx sdk.Context, supernodeAccount string) (sntypes.SuperNode, bool, error)

SetSuperNode(ctx sdk.Context, supernode sntypes.SuperNode) error
}
Expand Down
15 changes: 15 additions & 0 deletions x/supernode/v1/module/simulation.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ const (
// TODO: Determine the simulation weight value
defaultWeightMsgUpdateSupernode int = 100

opWeightMsgUpdateSupernodeInvalidAccount = "op_weight_msg_update_supernode_invalid_account"
// TODO: Determine the simulation weight value
defaultWeightMsgUpdateSupernodeInvalidAccount int = 20

// this line is used by starport scaffolding # simapp/module/const
)

Expand Down Expand Up @@ -121,6 +125,17 @@ func (am AppModule) WeightedOperations(simState module.SimulationState) []simtyp
supernodesimulation.SimulateMsgUpdateSupernode(am.accountKeeper, am.bankKeeper, am.keeper),
))

var weightMsgUpdateSupernodeInvalidAccount int
simState.AppParams.GetOrGenerate(opWeightMsgUpdateSupernodeInvalidAccount, &weightMsgUpdateSupernodeInvalidAccount, nil,
func(_ *rand.Rand) {
weightMsgUpdateSupernodeInvalidAccount = defaultWeightMsgUpdateSupernodeInvalidAccount
},
)
operations = append(operations, simulation.NewWeightedOperation(
weightMsgUpdateSupernodeInvalidAccount,
supernodesimulation.SimulateMsgUpdateSupernodeInvalidAccount(am.accountKeeper, am.bankKeeper, am.keeper),
))

// this line is used by starport scaffolding # simapp/module/operation

return operations
Expand Down
18 changes: 16 additions & 2 deletions x/supernode/v1/simulation/update_supernode.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,22 @@ func SimulateMsgUpdateSupernode(
}

if updateAccount {
newAcc, _ := simtypes.RandomAcc(r, accs)
supernodeAccount = newAcc.Address.String()
// Pick an account that is not already associated with another validator.
for i := 0; i < len(accs); i++ {
newAcc, _ := simtypes.RandomAcc(r, accs)
_, exists, err := k.GetSuperNodeByAccount(ctx, newAcc.Address.String())
if err != nil {
return simtypes.NoOpMsg(types.ModuleName, TypeMsgUpdateSupernode, err.Error()), nil, err
}
if !exists {
supernodeAccount = newAcc.Address.String()
break
}
}
// If no free account found, skip updating the supernode account.
if supernodeAccount == "" {
updateAccount = false
}
}

if updateVersion {
Expand Down
100 changes: 100 additions & 0 deletions x/supernode/v1/simulation/update_supernode_invalid_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package simulation

import (
"fmt"
"math/rand"

errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"

"github.com/LumeraProtocol/lumera/x/supernode/v1/keeper"
"github.com/LumeraProtocol/lumera/x/supernode/v1/types"
)

const (
TypeMsgUpdateSupernodeInvalidAccount = "update_supernode_invalid_account"
)

func SimulateMsgUpdateSupernodeInvalidAccount(
ak types.AccountKeeper,
bk types.BankKeeper,
k keeper.Keeper,
) simtypes.Operation {
return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
// Find a validator with an existing supernode.
var simAccount simtypes.Account
var validatorAddress string
var targetSupernodeAccount string
var found bool

stakingkeeper := k.GetStakingKeeper()
for i := 0; i < 10; i++ {
simAccount, _ = simtypes.RandomAcc(r, accs)
valAddr := sdk.ValAddress(simAccount.Address)

validator, err := stakingkeeper.Validator(ctx, valAddr)
if err != nil {
continue
}

supernode, exists := k.QuerySuperNode(ctx, valAddr)
if !exists || supernode.SupernodeAccount == "" {
continue
}

validatorAddress = validator.GetOperator()
targetSupernodeAccount = supernode.SupernodeAccount
found = true
break
}

if !found {
return simtypes.NoOpMsg(types.ModuleName, TypeMsgUpdateSupernodeInvalidAccount, "no eligible supernode found"), nil, nil
}

// Find another supernode account that belongs to a different validator.
var conflictAccount string
for i := 0; i < len(accs); i++ {
otherAcc, _ := simtypes.RandomAcc(r, accs)
if otherAcc.Address.Equals(simAccount.Address) {
continue
}

otherValAddr := sdk.ValAddress(otherAcc.Address)
otherSupernode, exists := k.QuerySuperNode(ctx, otherValAddr)
if !exists || otherSupernode.SupernodeAccount == "" {
continue
}

if otherSupernode.SupernodeAccount != targetSupernodeAccount {
conflictAccount = otherSupernode.SupernodeAccount
break
}
}

if conflictAccount == "" {
return simtypes.NoOpMsg(types.ModuleName, TypeMsgUpdateSupernodeInvalidAccount, "no conflicting supernode account found"), nil, nil
}

msg := &types.MsgUpdateSupernode{
Creator: simAccount.Address.String(),
ValidatorAddress: validatorAddress,
SupernodeAccount: conflictAccount,
}

msgServer := keeper.NewMsgServerImpl(k)
_, err := msgServer.UpdateSupernode(ctx, msg)
if err == nil {
return simtypes.NoOpMsg(types.ModuleName, TypeMsgUpdateSupernodeInvalidAccount, "expected invalid supernode account update to fail"), nil, fmt.Errorf("expected invalid supernode account update to fail")
}
if errorsmod.IsOf(err, sdkerrors.ErrInvalidRequest) {
return simtypes.NewOperationMsg(msg, true, "expected invalid supernode account update rejected"), nil, nil
}

return simtypes.NoOpMsg(types.ModuleName, TypeMsgUpdateSupernodeInvalidAccount, err.Error()), nil, err
}
}