diff --git a/PENDING.md b/PENDING.md index 46e861013..51d80bd5b 100644 --- a/PENDING.md +++ b/PENDING.md @@ -23,6 +23,7 @@ BREAKING CHANGES * [core] \#1807 Switch from use of rational to decimal * [types] \#1901 Validator interface's GetOwner() renamed to GetOperator() * [types] \#2119 Parsed error messages and ABCI log errors to make them more human readable. + * [simulation] Rename TestAndRunTx to Operation [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * Tendermint @@ -60,6 +61,7 @@ IMPROVEMENTS * SDK * [tools] Make get_vendor_deps deletes `.vendor-new` directories, in case scratch files are present. * [cli] \#1632 Add integration tests to ensure `basecoind init && basecoind` start sequences run successfully for both `democoin` and `basecoin` examples. + * [simulation] Make timestamps randomized [#2153](https://github.com/cosmos/cosmos-sdk/pull/2153) * Tendermint diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 5fa75a931..9036c7e14 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -85,8 +85,8 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json return appState } -func testAndRunTxs(app *GaiaApp) []simulation.TestAndRunTx { - return []simulation.TestAndRunTx{ +func testAndRunTxs(app *GaiaApp) []simulation.Operation { + return []simulation.Operation{ banksim.TestAndRunSingleInputMsgSend(app.accountMapper), govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index 43d7e1fd7..633f6787f 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -20,7 +20,7 @@ import ( // TestAndRunSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both // accounts already exist. -func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.TestAndRunTx { +func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { fromKey := simulation.RandomKey(r, keys) fromAddr := sdk.AccAddress(fromKey.PubKey().Address()) diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 8fedeca79..88e7a5f3a 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -33,7 +33,7 @@ func TestBankWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.TestAndRunTx{ + []simulation.Operation{ TestAndRunSingleInputMsgSend(mapper), }, []simulation.RandSetup{}, diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index ed80ab4e6..f270d3a7d 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -21,7 +21,7 @@ const ( ) // SimulateMsgSubmitProposal -func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) @@ -50,7 +50,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd } // SimulateMsgDeposit -func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) @@ -77,7 +77,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { } // SimulateMsgVote -func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go index 691aa1cd2..6f0f9830c 100644 --- a/x/gov/simulation/sim_test.go +++ b/x/gov/simulation/sim_test.go @@ -55,7 +55,7 @@ func TestGovWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.TestAndRunTx{ + []simulation.Operation{ SimulateMsgSubmitProposal(govKeeper, stakeKeeper), SimulateMsgDeposit(govKeeper, stakeKeeper), SimulateMsgVote(govKeeper, stakeKeeper), diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index c7e616614..5b1d4030c 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -3,6 +3,7 @@ package simulation import ( "encoding/json" "fmt" + "math" "math/rand" "sort" "testing" @@ -20,7 +21,7 @@ import ( // Simulate tests application by sending random messages. func Simulate( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { time := time.Now().UnixNano() @@ -30,12 +31,20 @@ func Simulate( // SimulateFromSeed tests an application by running the provided // operations, testing the provided invariants, but using the provided seed. func SimulateFromSeed( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, + t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []Operation, setups []RandSetup, invariants []Invariant, numBlocks int, blockSize int, commit bool, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) - fmt.Printf("%s\n", log) r := rand.New(rand.NewSource(seed)) + + unixTime := r.Int63n(int64(math.Pow(2, 40))) + + // Set the timestamp for simulation + timestamp := time.Unix(unixTime, 0) + log = fmt.Sprintf("%s\nStarting the simulation from time %v, unixtime %v", log, timestamp.UTC().Format(time.UnixDate), timestamp.Unix()) + fmt.Printf("%s\n", log) + timeDiff := maxTimePerBlock - minTimePerBlock + keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) // Setup event stats @@ -45,9 +54,6 @@ func SimulateFromSeed( events[what]++ } - timestamp := time.Unix(0, 0) - timeDiff := maxTimePerBlock - minTimePerBlock - res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) validators := make(map[string]mockValidator) for _, validator := range res.Validators { diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 35769b0b2..3ece3c2e9 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -11,10 +11,15 @@ import ( ) type ( - // TestAndRunTx produces a fuzzed transaction, and ensures the state - // transition was as expected. It returns a descriptive message "action" - // about what this fuzzed tx actually did, for ease of debugging. - TestAndRunTx func( + // Operation runs a state machine transition, + // and ensures the transition happened as expected. + // The operation could be running and testing a fuzzed transaction, + // or doing the same for a message. + // + // For ease of debugging, + // an operation returns a descriptive message "action", + // which details what this fuzzed state machine transition actually did. + Operation func( t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, privKeys []crypto.PrivKey, log string, event func(string), ) (action string, err sdk.Error) diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go index 8ef24493b..e694bd1d7 100644 --- a/x/slashing/simulation/msgs.go +++ b/x/slashing/simulation/msgs.go @@ -16,7 +16,7 @@ import ( ) // SimulateMsgUnjail -func SimulateMsgUnjail(k slashing.Keeper) simulation.TestAndRunTx { +func SimulateMsgUnjail(k slashing.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { key := simulation.RandomKey(r, keys) address := sdk.AccAddress(key.PubKey().Address()) diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index 17f980893..995e4f358 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -18,7 +18,7 @@ import ( ) // SimulateMsgCreateValidator -func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom description := stake.Description{ @@ -55,7 +55,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation } // SimulateMsgEditValidator -func SimulateMsgEditValidator(k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { description := stake.Description{ Moniker: simulation.RandStringOfLength(r, 10), @@ -83,7 +83,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.TestAndRunTx { } // SimulateMsgDelegate -func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -115,7 +115,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAn } // SimulateMsgBeginUnbonding -func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom validatorKey := simulation.RandomKey(r, keys) @@ -147,7 +147,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation. } // SimulateMsgCompleteUnbonding -func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { validatorKey := simulation.RandomKey(r, keys) validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address()) @@ -170,7 +170,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.TestAndRunTx { } // SimulateMsgBeginRedelegate -func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { denom := k.GetParams(ctx).BondDenom sourceValidatorKey := simulation.RandomKey(r, keys) @@ -206,7 +206,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation } // SimulateMsgCompleteRedelegate -func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.TestAndRunTx { +func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation { return func(t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, err sdk.Error) { validatorSrcKey := simulation.RandomKey(r, keys) validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address()) diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 84745cd1d..c5d301c56 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -44,7 +44,7 @@ func TestStakeWithRandomMessages(t *testing.T) { simulation.Simulate( t, mapp.BaseApp, appStateFn, - []simulation.TestAndRunTx{ + []simulation.Operation{ SimulateMsgCreateValidator(mapper, stakeKeeper), SimulateMsgEditValidator(stakeKeeper), SimulateMsgDelegate(mapper, stakeKeeper),