feat(sims): Add sims2 framework and factory methods (backport #21613) (#21752)

Co-authored-by: Alexander Peters <alpe@users.noreply.github.com>
Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
mergify[bot]
2024-09-17 10:04:02 +00:00
committed by GitHub
co-authored by Alexander Peters Julien Robert
parent 391d4d72fb
commit 8823508147
140 changed files with 4899 additions and 9914 deletions
+22 -45
View File
@@ -18,27 +18,31 @@ import (
// AppModuleSimulation defines the standard functions that every module should expose
// for the SDK blockchain simulator
type AppModuleSimulation interface {
// randomized genesis states
// GenerateGenesisState randomized genesis states
GenerateGenesisState(input *SimulationState)
// register a func to decode the each module's defined types from their corresponding store key
// RegisterStoreDecoder register a func to decode the each module's defined types from their corresponding store key
RegisterStoreDecoder(simulation.StoreDecoderRegistry)
// simulation operations (i.e msgs) with their respective weight
WeightedOperations(simState SimulationState) []simulation.WeightedOperation
}
type (
HasLegacyWeightedOperations interface {
// WeightedOperations simulation operations (i.e msgs) with their respective weight
WeightedOperations(simState SimulationState) []simulation.WeightedOperation
}
// HasLegacyProposalMsgs defines the messages that can be used to simulate governance (v1) proposals
// Deprecated replaced by HasProposalMsgsX
HasLegacyProposalMsgs interface {
// ProposalMsgs msg functions used to simulate governance proposals
ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg
}
// HasProposalMsgs defines the messages that can be used to simulate governance (v1) proposals
type HasProposalMsgs interface {
// msg functions used to simulate governance proposals
ProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg
}
// HasProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals
type HasProposalContents interface {
// content functions used to simulate governance proposals
ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}
// HasLegacyProposalContents defines the contents that can be used to simulate legacy governance (v1beta1) proposals
// Deprecated replaced by HasProposalMsgsX
HasLegacyProposalContents interface {
// ProposalContents content functions used to simulate governance proposals
ProposalContents(simState SimulationState) []simulation.WeightedProposalContent //nolint:staticcheck // legacy v1beta1 governance
}
)
// SimulationManager defines a simulation manager that provides the high level utility
// for managing and executing simulation functionalities for a group of modules
@@ -64,14 +68,13 @@ func NewSimulationManager(modules ...AppModuleSimulation) *SimulationManager {
// Then it attempts to cast every provided AppModule into an AppModuleSimulation.
// If the cast succeeds, its included, otherwise it is excluded.
func NewSimulationManagerFromAppModules(modules map[string]appmodule.AppModule, overrideModules map[string]AppModuleSimulation) *SimulationManager {
simModules := []AppModuleSimulation{}
appModuleNamesSorted := make([]string, 0, len(modules))
for moduleName := range modules {
appModuleNamesSorted = append(appModuleNamesSorted, moduleName)
}
sort.Strings(appModuleNamesSorted)
var simModules []AppModuleSimulation
for _, moduleName := range appModuleNamesSorted {
// for every module, see if we override it. If so, use override.
// Else, if we can cast the app module into a simulation module add it.
@@ -95,7 +98,7 @@ func NewSimulationManagerFromAppModules(modules map[string]appmodule.AppModule,
func (sm *SimulationManager) GetProposalContents(simState SimulationState) []simulation.WeightedProposalContent {
wContents := make([]simulation.WeightedProposalContent, 0, len(sm.Modules))
for _, module := range sm.Modules {
if module, ok := module.(HasProposalContents); ok {
if module, ok := module.(HasLegacyProposalContents); ok {
wContents = append(wContents, module.ProposalContents(simState)...)
}
}
@@ -103,19 +106,6 @@ func (sm *SimulationManager) GetProposalContents(simState SimulationState) []sim
return wContents
}
// GetProposalMsgs returns each module's proposal msg generator function
// with their default operation weight and key.
func (sm *SimulationManager) GetProposalMsgs(simState SimulationState) []simulation.WeightedProposalMsg {
wContents := make([]simulation.WeightedProposalMsg, 0, len(sm.Modules))
for _, module := range sm.Modules {
if module, ok := module.(HasProposalMsgs); ok {
wContents = append(wContents, module.ProposalMsgs(simState)...)
}
}
return wContents
}
// RegisterStoreDecoders registers each of the modules' store decoders into a map
func (sm *SimulationManager) RegisterStoreDecoders() {
for _, module := range sm.Modules {
@@ -131,16 +121,6 @@ func (sm *SimulationManager) GenerateGenesisStates(simState *SimulationState) {
}
}
// WeightedOperations returns all the modules' weighted operations of an application
func (sm *SimulationManager) WeightedOperations(simState SimulationState) []simulation.WeightedOperation {
wOps := make([]simulation.WeightedOperation, 0, len(sm.Modules))
for _, module := range sm.Modules {
wOps = append(wOps, module.WeightedOperations(simState)...)
}
return wOps
}
// SimulationState is the input parameters used on each of the module's randomized
// GenesisState generator function
type SimulationState struct {
@@ -158,7 +138,4 @@ type SimulationState struct {
GenTimestamp time.Time // genesis timestamp
UnbondTime time.Duration // staking unbond time stored to use it as the slashing maximum evidence duration
LegacyParamChange []simulation.LegacyParamChange // simulated parameter changes from modules
//nolint:staticcheck // legacy used for testing
LegacyProposalContents []simulation.WeightedProposalContent // proposal content generator functions with their default weight and app sim key
ProposalMsgs []simulation.WeightedProposalMsg // proposal msg generator functions with their default weight and app sim key
}
+10 -8
View File
@@ -14,10 +14,11 @@ import (
// eventually more useful data can be placed in here.
// (e.g. number of coins)
type Account struct {
PrivKey cryptotypes.PrivKey
PubKey cryptotypes.PubKey
Address sdk.AccAddress
ConsKey cryptotypes.PrivKey
PrivKey cryptotypes.PrivKey
PubKey cryptotypes.PubKey
Address sdk.AccAddress
ConsKey cryptotypes.PrivKey
AddressBech32 string
}
// Equals returns true if two accounts are equal
@@ -50,10 +51,11 @@ func RandomAccounts(r *rand.Rand, n int) []Account {
}
idx[string(addr.Bytes())] = struct{}{}
accs[i] = Account{
Address: addr,
PrivKey: privKey,
PubKey: pubKey,
ConsKey: ed25519.GenPrivKeyFromSecret(privkeySeed),
Address: addr,
PrivKey: privKey,
PubKey: pubKey,
ConsKey: ed25519.GenPrivKeyFromSecret(privkeySeed),
AddressBech32: addr.String(),
}
i++
}
+5 -4
View File
@@ -25,7 +25,8 @@ type Config struct {
DBBackend string // custom db backend type
BlockMaxGas int64 // custom max gas for block
FuzzSeed []byte
T testing.TB
TB testing.TB
FauxMerkle bool
}
func (c Config) shallowCopy() Config {
@@ -33,10 +34,10 @@ func (c Config) shallowCopy() Config {
}
// With sets the values of t, seed, and fuzzSeed in a copy of the Config and returns the copy.
func (c Config) With(t *testing.T, seed int64, fuzzSeed []byte) Config {
t.Helper()
func (c Config) With(tb testing.TB, seed int64, fuzzSeed []byte) Config {
tb.Helper()
r := c.shallowCopy()
r.T = t
r.TB = tb
r.Seed = seed
r.FuzzSeed = fuzzSeed
return r
+15 -14
View File
@@ -3,12 +3,9 @@ package simulation
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"time"
"github.com/cosmos/gogoproto/proto"
"cosmossdk.io/core/address"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -20,6 +17,17 @@ type AppEntrypoint interface {
SimDeliver(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error)
}
var _ AppEntrypoint = SimDeliverFn(nil)
type (
AppEntrypointFn = SimDeliverFn
SimDeliverFn func(_txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error)
)
func (m SimDeliverFn) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk.Result, error) {
return m(txEncoder, tx)
}
// Deprecated: Use WeightedProposalMsg instead.
type WeightedProposalContent interface {
AppParamsKey() string // key used to retrieve the value of the weight from the simulation application params
@@ -28,7 +36,7 @@ type WeightedProposalContent interface {
}
// Deprecated: Use MsgSimulatorFn instead.
type ContentSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) Content
type ContentSimulatorFn func(r *rand.Rand, ctx context.Context, accs []Account) Content
// Deprecated: Use MsgSimulatorFn instead.
type Content interface {
@@ -85,17 +93,15 @@ type OperationMsg struct {
Name string `json:"name" yaml:"name"` // operation name (msg Type or "no-operation")
Comment string `json:"comment" yaml:"comment"` // additional comment
OK bool `json:"ok" yaml:"ok"` // success
Msg []byte `json:"msg" yaml:"msg"` // protobuf encoded msg
}
// NewOperationMsgBasic creates a new operation message from raw input.
func NewOperationMsgBasic(moduleName, msgType, comment string, ok bool, msg []byte) OperationMsg {
func NewOperationMsgBasic(moduleName, msgType, comment string, ok bool) OperationMsg {
return OperationMsg{
Route: moduleName,
Name: msgType,
Comment: comment,
OK: ok,
Msg: msg,
}
}
@@ -106,17 +112,12 @@ func NewOperationMsg(msg sdk.Msg, ok bool, comment string) OperationMsg {
if moduleName == "" {
moduleName = msgType
}
protoBz, err := proto.Marshal(msg)
if err != nil {
panic(fmt.Errorf("failed to marshal proto message: %w", err))
}
return NewOperationMsgBasic(moduleName, msgType, comment, ok, protoBz)
return NewOperationMsgBasic(moduleName, msgType, comment, ok)
}
// NoOpMsg - create a no-operation message
func NoOpMsg(moduleName, msgType, comment string) OperationMsg {
return NewOperationMsgBasic(moduleName, msgType, comment, false, nil)
return NewOperationMsgBasic(moduleName, msgType, comment, false)
}
// log entry text for this operation msg