Skip to content

Commit

Permalink
refactor!: extract AppStateFn out of simapp (#14977)
Browse files Browse the repository at this point in the history
(cherry picked from commit 4f13b5b)

# Conflicts:
#	CHANGELOG.md
#	crypto/keys/secp256k1/secp256k1_test.go
#	testutil/sims/state_helpers.go
  • Loading branch information
julienrbrt authored and mergify[bot] committed Feb 9, 2023
1 parent a393336 commit f39b7fe
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 38 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,25 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

<<<<<<< HEAD
=======
* (simapp) [#14977](https://github.com/cosmos/cosmos-sdk/pull/14977) Move simulation helpers functions (`AppStateFn` and `AppStateRandomizedFn`) to `testutil/sims`. These takes an extra genesisState argument which is the default state of the app.
* (x/gov) [#14720](https://github.com/cosmos/cosmos-sdk/pull/14720) Add an expedited field in the gov v1 proposal and `MsgNewMsgProposal`.
* [#14847](https://github.com/cosmos/cosmos-sdk/pull/14847) App and ModuleManager methods `InitGenesis`, `ExportGenesis`, `BeginBlock` and `EndBlock` now also return an error.
* (simulation) [#14728](https://github.com/cosmos/cosmos-sdk/pull/14728) Rename the `ParamChanges` field to `LegacyParamChange` and `Contents` to `LegacyProposalContents` in `simulation.SimulationState`. Additionally it adds a `ProposalMsgs` field to `simulation.SimulationState`.
* (x/upgrade) [#14764](https://github.com/cosmos/cosmos-sdk/pull/14764) The `x/upgrade` module is extracted to have a separate go.mod file which allows it to be a standalone module.
* (x/gov) [#14782](https://github.com/cosmos/cosmos-sdk/pull/14782) Move the `metadata` argument in `govv1.NewProposal` alongside `title` and `summary`.
* (store) [#14746](https://github.com/cosmos/cosmos-sdk/pull/14746) Extract Store in its own go.mod and rename the package to `cosmossdk.io/store`.
* (simulation) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove the `MsgType` field from `simulation.OperationInput` struct.
* (crypto/keyring) [#13734](https://github.com/cosmos/cosmos-sdk/pull/13834) The keyring's `Sign` method now takes a new `signMode` argument. It is only used if the signing key is a Ledger hardware device. You can set it to 0 in all other cases.
* (x/evidence) [14724](https://github.com/cosmos/cosmos-sdk/pull/14724) Extract Evidence in its own go.mod and rename the package to `cosmossdk.io/x/evidence`.
* (x/nft) [#14725](https://github.com/cosmos/cosmos-sdk/pull/14725) Extract NFT in its own go.mod and rename the package to `cosmossdk.io/x/nft`.
* (tx) [#14634](https://github.com/cosmos/cosmos-sdk/pull/14634) Move the `tx` go module to `x/tx`.
* (snapshots) [#14597](https://github.com/cosmos/cosmos-sdk/pull/14597) Move `snapshots` to `store/snapshots`, rename and bump proto package to v1.
* (crypto/keyring) [#14151](https://github.com/cosmos/cosmos-sdk/pull/14151) Move keys presentation from `crypto/keyring` to `client/keys`
* (modules) [#13850](https://github.com/cosmos/cosmos-sdk/pull/13850) and [#14046](https://github.com/cosmos/cosmos-sdk/pull/14046) Remove gogoproto stringer annotations. This removes the custom `String()` methods on all types that were using the annotations.
* (x/auth) [#13850](https://github.com/cosmos/cosmos-sdk/pull/13850/) Remove `MarshalYAML` methods from module (`x/...`) types.
>>>>>>> 4f13b5b31 (refactor!: extract `AppStateFn` out of simapp (#14977))
* (x/auth) [#13877](https://github.com/cosmos/cosmos-sdk/pull/13877) Rename `AccountKeeper`'s `GetNextAccountNumber` to `NextAccountNumber`.
* (x/evidence) [#13740](https://github.com/cosmos/cosmos-sdk/pull/13740) The `NewQueryEvidenceRequest` function now takes `hash` as a HEX encoded `string`.
* (server) [#13485](https://github.com/cosmos/cosmos-sdk/pull/13485) The `Application` service now requires the `RegisterNodeService` method to be implemented.
Expand Down
86 changes: 86 additions & 0 deletions crypto/keys/secp256k1/secp256k1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,92 @@ type keyData struct {
addr string
}

<<<<<<< HEAD
=======
/*
The following code snippet has been used to generate test vectors. The purpose of these vectors are to check our
implementation of secp256k1 against go-ethereum's one. It has been commented to avoid dependencies.
github.com/btcsuite/btcutil v1.0.2
github.com/ethereum/go-ethereum v1.10.26
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
---
import (
"crypto/ecdsa"
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/btcsuite/btcutil/base58"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/ripemd160"
)
func ethereumKeys() keyData {
// Generate private key with the go-ethereum
priv, err := crypto.GenerateKey()
if err != nil {
panic(err)
}
encPriv := make([]byte, len(priv.D.Bytes())*2)
hex.Encode(encPriv, priv.D.Bytes())
// Get go-ethereum public key
ethPub, ok := priv.Public().(*ecdsa.PublicKey)
if !ok {
panic(err)
}
ethPublicKeyBytes := crypto.FromECDSAPub(ethPub)
// Format byte depending on the oddness of the Y coordinate.
format := 0x02
if ethPub.Y.Bit(0) != 0 {
format = 0x03
}
// Public key in the 33-byte compressed format.
pub := ethPublicKeyBytes[:33]
encPub := make([]byte, len(pub)*2)
pub[0] = byte(format)
hex.Encode(encPub, pub)
// Bitcoin style addresses
sha := sha256.Sum256(pub)
hasherRIPEMD160 := ripemd160.New()
hasherRIPEMD160.Write(sha[:])
addr := hasherRIPEMD160.Sum(nil)
return keyData{
priv: string(encPriv),
pub: string(encPub),
addr: base58.CheckEncode(addr[:], 0),
}
}
*/

/*
generateKeyForCheckingConsistency was used to create test vectors that matches consistency against prior versions.
Here are the specific versions used to generate the vectors.
github.com/cosmos/btcutil v1.0.5
github.com/cosmos/cosmos-sdk v0.46.8
*/
var _ = func() keyData {
priv := secp256k1.GenPrivKey()
encPriv := make([]byte, len(priv.Key)*2)
hex.Encode(encPriv, priv.Key)
pub := priv.PubKey()
encPub := make([]byte, len(pub.Bytes())*2)
hex.Encode(encPub, pub.Bytes())
addr := pub.Address()
return keyData{
priv: string(encPriv),
pub: string(encPub),
addr: base58.CheckEncode(addr, 0),
}
}

>>>>>>> 4f13b5b31 (refactor!: extract `AppStateFn` out of simapp (#14977))
var secpDataTable = []keyData{
{
priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330",
Expand Down
2 changes: 1 addition & 1 deletion simapp/app_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func NewSimApp(
// For providing a custom a base account type add it below.
// By default the auth module uses authtypes.ProtoBaseAccount().
//
// func() authtypes.AccountI { return authtypes.ProtoBaseAccount() },
// func() sdk.AccountI { return authtypes.ProtoBaseAccount() },

//
// MINT
Expand Down
7 changes: 0 additions & 7 deletions simapp/params/params.go

This file was deleted.

4 changes: 2 additions & 2 deletions simapp/sim_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func BenchmarkFullAppSimulation(b *testing.B) {
b,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -104,7 +104,7 @@ func BenchmarkInvariants(b *testing.B) {
b,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down
10 changes: 5 additions & 5 deletions simapp/sim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestFullAppSimulation(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -137,7 +137,7 @@ func TestAppImportExport(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -253,7 +253,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -301,7 +301,7 @@ func TestAppSimulationAfterImport(t *testing.T) {
t,
os.Stdout,
newApp.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config),
BlockedAddresses(),
Expand Down Expand Up @@ -356,7 +356,7 @@ func TestAppStateDeterminism(t *testing.T) {
t,
os.Stdout,
app.BaseApp,
AppStateFn(app.AppCodec(), app.SimulationManager()),
simtestutil.AppStateFn(app.AppCodec(), app.SimulationManager(), app.DefaultGenesis()),
simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1
simtestutil.SimulationOperations(app, app.AppCodec(), config),
BlockedAddresses(),
Expand Down
77 changes: 54 additions & 23 deletions simapp/state.go → testutil/sims/state_helpers.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package simapp
package sims

import (
"encoding/json"
Expand All @@ -8,11 +8,18 @@ import (
"os"
"time"

<<<<<<< HEAD:simapp/state.go
tmjson "github.com/tendermint/tendermint/libs/json"
tmtypes "github.com/tendermint/tendermint/types"

"cosmossdk.io/math"
simappparams "cosmossdk.io/simapp/params"
=======
"cosmossdk.io/math"
cmtjson "github.com/cometbft/cometbft/libs/json"
cmttypes "github.com/cometbft/cometbft/types"

>>>>>>> 4f13b5b31 (refactor!: extract `AppStateFn` out of simapp (#14977)):testutil/sims/state_helpers.go
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -24,11 +31,21 @@ import (
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

// Simulation parameter constants
const (
StakePerAccount = "stake_per_account"
InitiallyBondedValidators = "initially_bonded_validators"
)

// AppStateFn returns the initial application state using a genesis or the simulation parameters.
// It panics if the user provides files for both of them.
// If a file is not given for the genesis or the sim params, it creates a randomized one.
func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn {
return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config,
// genesisState is the default genesis state of the whole app.
func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager, genesisState map[string]json.RawMessage) simtypes.AppStateFn {
return func(
r *rand.Rand,
accs []simtypes.Account,
config simtypes.Config,
) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) {
if simcli.FlagGenesisTimeValue == 0 {
genesisTimestamp = simtypes.RandTimestamp(r)
Expand All @@ -43,7 +60,10 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty

case config.GenesisFile != "":
// override the default chain-id from simapp to set it later to the config
genesisDoc, accounts := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile)
genesisDoc, accounts, err := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile)
if err != nil {
panic(err)
}

if simcli.FlagGenesisTimeValue == 0 {
// use genesis timestamp if no custom timestamp is provided (i.e no random timestamp)
Expand All @@ -65,11 +85,11 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
if err != nil {
panic(err)
}
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState)

default:
appParams := make(simtypes.AppParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams)
appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams, genesisState)
}

rawState := make(map[string]json.RawMessage)
Expand All @@ -84,8 +104,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
}

stakingState := new(stakingtypes.GenesisState)
err = cdc.UnmarshalJSON(stakingStateBz, stakingState)
if err != nil {
if err = cdc.UnmarshalJSON(stakingStateBz, stakingState); err != nil {
panic(err)
}
// compute not bonded balance
Expand All @@ -104,8 +123,7 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
panic("bank genesis state is missing")
}
bankState := new(banktypes.GenesisState)
err = cdc.UnmarshalJSON(bankStateBz, bankState)
if err != nil {
if err = cdc.UnmarshalJSON(bankStateBz, bankState); err != nil {
panic(err)
}

Expand Down Expand Up @@ -140,24 +158,27 @@ func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simty
// AppStateRandomizedFn creates calls each module's GenesisState generator function
// and creates the simulation params
func AppStateRandomizedFn(
simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec,
accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams,
simManager *module.SimulationManager,
r *rand.Rand,
cdc codec.JSONCodec,
accs []simtypes.Account,
genesisTimestamp time.Time,
appParams simtypes.AppParams,
genesisState map[string]json.RawMessage,
) (json.RawMessage, []simtypes.Account) {
numAccs := int64(len(accs))
genesisState := ModuleBasics.DefaultGenesis(cdc)

// generate a random amount of initial stake coins and a random initial
// number of bonded accounts
var (
numInitiallyBonded int64
initialStake math.Int
)
appParams.GetOrGenerate(
cdc, simappparams.StakePerAccount, &initialStake, r,
cdc, StakePerAccount, &initialStake, r,
func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) },
)
appParams.GetOrGenerate(
cdc, simappparams.InitiallyBondedValidators, &numInitiallyBonded, r,
cdc, InitiallyBondedValidators, &numInitiallyBonded, r,
func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) },
)

Expand Down Expand Up @@ -197,23 +218,33 @@ func AppStateRandomizedFn(

// AppStateFromGenesisFileFn util function to generate the genesis AppState
// from a genesis.json file.
<<<<<<< HEAD:simapp/state.go
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account) {
=======
func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (cmttypes.GenesisDoc, []simtypes.Account, error) {
>>>>>>> 4f13b5b31 (refactor!: extract `AppStateFn` out of simapp (#14977)):testutil/sims/state_helpers.go
bytes, err := os.ReadFile(genesisFile)
if err != nil {
panic(err)
}

<<<<<<< HEAD:simapp/state.go
var genesis tmtypes.GenesisDoc
// NOTE: Tendermint uses a custom JSON decoder for GenesisDoc
err = tmjson.Unmarshal(bytes, &genesis)
if err != nil {
panic(err)
=======
var genesis cmttypes.GenesisDoc
// NOTE: CometBFT uses a custom JSON decoder for GenesisDoc
if err = cmtjson.Unmarshal(bytes, &genesis); err != nil {
return genesis, nil, err
>>>>>>> 4f13b5b31 (refactor!: extract `AppStateFn` out of simapp (#14977)):testutil/sims/state_helpers.go
}

var appState GenesisState
err = json.Unmarshal(genesis.AppState, &appState)
if err != nil {
panic(err)
var appState map[string]json.RawMessage
if err = json.Unmarshal(genesis.AppState, &appState); err != nil {
return genesis, nil, err
}

var authGenesis authtypes.GenesisState
Expand All @@ -233,15 +264,15 @@ func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile str

privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed)

a, ok := acc.GetCachedValue().(authtypes.AccountI)
a, ok := acc.GetCachedValue().(sdk.AccountI)
if !ok {
panic("expected account")
return genesis, nil, fmt.Errorf("expected account")
}

// create simulator accounts
simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress()}
newAccs[i] = simAcc
}

return genesis, newAccs
return genesis, newAccs, nil
}

0 comments on commit f39b7fe

Please sign in to comment.