simulation: Add benchmarking
This commit is contained in:
parent
fd8c1e5253
commit
46bbada4ee
|
@ -45,6 +45,7 @@ FEATURES
|
|||
* SDK
|
||||
* [querier] added custom querier functionality, so ABCI query requests can be handled by keepers
|
||||
* [simulation] \#1924 allow operations to specify future operations
|
||||
* [simulation] Add benchmarking capabilities
|
||||
|
||||
* Tendermint
|
||||
|
||||
|
|
|
@ -112,6 +112,27 @@ func invariants(app *GaiaApp) []simulation.Invariant {
|
|||
}
|
||||
}
|
||||
|
||||
// Profile with:
|
||||
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -cpuprofile cpu.out
|
||||
func BenchmarkFullGaiaSimulation(b *testing.B) {
|
||||
// Setup Gaia application
|
||||
var logger log.Logger
|
||||
logger = log.NewNopLogger()
|
||||
db := dbm.NewMemDB()
|
||||
app := NewGaiaApp(logger, db, nil)
|
||||
|
||||
// Run randomized simulation
|
||||
// TODO parameterize numbers, save for a later PR
|
||||
simulation.BenchmarkSimulationFromSeed(
|
||||
b, app.BaseApp, appStateFn, seed,
|
||||
testAndRunTxs(app),
|
||||
[]simulation.RandSetup{},
|
||||
10,
|
||||
100,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
func TestFullGaiaSimulation(t *testing.T) {
|
||||
if !enabled {
|
||||
t.Skip("Skipping Gaia simulation")
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
// SimulateSingleInputMsgSend tests and runs a single msg send, with one input and one output, where both
|
||||
// accounts already exist.
|
||||
func SimulateSingleInputMsgSend(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, fOps []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) {
|
||||
fromKey := simulation.RandomKey(r, keys)
|
||||
fromAddr := sdk.AccAddress(fromKey.PubKey().Address())
|
||||
toKey := simulation.RandomKey(r, keys)
|
||||
|
@ -58,7 +58,7 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation
|
|||
Inputs: []bank.Input{bank.NewInput(fromAddr, coins)},
|
||||
Outputs: []bank.Output{bank.NewOutput(toAddr, coins)},
|
||||
}
|
||||
sendAndVerifyMsgSend(t, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey})
|
||||
sendAndVerifyMsgSend(tb, app, mapper, msg, ctx, log, []crypto.PrivKey{fromKey})
|
||||
event("bank/sendAndVerifyMsgSend/ok")
|
||||
|
||||
return action, nil, nil
|
||||
|
@ -66,7 +66,7 @@ func SimulateSingleInputMsgSend(mapper auth.AccountMapper) simulation.Operation
|
|||
}
|
||||
|
||||
// Sends and verifies the transition of a msg send. This fails if there are repeated inputs or outputs
|
||||
func sendAndVerifyMsgSend(t *testing.T, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) {
|
||||
func sendAndVerifyMsgSend(tb testing.TB, app *baseapp.BaseApp, mapper auth.AccountMapper, msg bank.MsgSend, ctx sdk.Context, log string, privkeys []crypto.PrivKey) {
|
||||
initialInputAddrCoins := make([]sdk.Coins, len(msg.Inputs))
|
||||
initialOutputAddrCoins := make([]sdk.Coins, len(msg.Outputs))
|
||||
AccountNumbers := make([]int64, len(msg.Inputs))
|
||||
|
@ -91,12 +91,12 @@ func sendAndVerifyMsgSend(t *testing.T, app *baseapp.BaseApp, mapper auth.Accoun
|
|||
// TODO: Do this in a more 'canonical' way
|
||||
fmt.Println(res)
|
||||
fmt.Println(log)
|
||||
t.FailNow()
|
||||
tb.FailNow()
|
||||
}
|
||||
|
||||
for i := 0; i < len(msg.Inputs); i++ {
|
||||
terminalInputCoins := mapper.GetAccount(ctx, msg.Inputs[i].Address).GetCoins()
|
||||
require.Equal(t,
|
||||
require.Equal(tb,
|
||||
initialInputAddrCoins[i].Minus(msg.Inputs[i].Coins),
|
||||
terminalInputCoins,
|
||||
fmt.Sprintf("Input #%d had an incorrect amount of coins\n%s", i, log),
|
||||
|
@ -104,11 +104,9 @@ func sendAndVerifyMsgSend(t *testing.T, app *baseapp.BaseApp, mapper auth.Accoun
|
|||
}
|
||||
for i := 0; i < len(msg.Outputs); i++ {
|
||||
terminalOutputCoins := mapper.GetAccount(ctx, msg.Outputs[i].Address).GetCoins()
|
||||
require.Equal(t,
|
||||
initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins),
|
||||
terminalOutputCoins,
|
||||
fmt.Sprintf("Output #%d had an incorrect amount of coins\n%s", i, log),
|
||||
)
|
||||
if !terminalOutputCoins.IsEqual(initialOutputAddrCoins[i].Plus(msg.Outputs[i].Coins)) {
|
||||
tb.Fatalf("Output #%d had an incorrect amount of coins\n%s", i, log)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
|
@ -23,24 +21,15 @@ const (
|
|||
// SimulateMsgSubmitProposal simulates a msg Submit Proposal
|
||||
// Note: Currently doesn't ensure that the proposal txt is in JSON form
|
||||
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, fOps []simulation.FutureOperation, err sdk.Error) {
|
||||
key := simulation.RandomKey(r, keys)
|
||||
addr := sdk.AccAddress(key.PubKey().Address())
|
||||
deposit := randomDeposit(r)
|
||||
msg := gov.NewMsgSubmitProposal(
|
||||
simulation.RandStringOfLength(r, 5),
|
||||
simulation.RandStringOfLength(r, 5),
|
||||
gov.ProposalTypeText,
|
||||
addr,
|
||||
deposit,
|
||||
)
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
handler := gov.NewHandler(k)
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOps []simulation.FutureOperation, err sdk.Error) {
|
||||
msg := simulationCreateMsgSubmitProposal(tb, r, keys, log)
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := gov.NewHandler(k)(ctx, msg)
|
||||
result := handler(ctx, msg)
|
||||
if result.IsOK() {
|
||||
// Update pool to keep invariants
|
||||
pool := sk.GetPool(ctx)
|
||||
pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(deposit.AmountOf(denom)))
|
||||
pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewDecFromInt(msg.InitialDeposit.AmountOf(denom)))
|
||||
sk.SetPool(ctx, pool)
|
||||
write()
|
||||
}
|
||||
|
@ -50,9 +39,26 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.Operati
|
|||
}
|
||||
}
|
||||
|
||||
func simulationCreateMsgSubmitProposal(tb testing.TB, r *rand.Rand, keys []crypto.PrivKey, log string) gov.MsgSubmitProposal {
|
||||
key := simulation.RandomKey(r, keys)
|
||||
addr := sdk.AccAddress(key.PubKey().Address())
|
||||
deposit := randomDeposit(r)
|
||||
msg := gov.NewMsgSubmitProposal(
|
||||
simulation.RandStringOfLength(r, 5),
|
||||
simulation.RandStringOfLength(r, 5),
|
||||
gov.ProposalTypeText,
|
||||
addr,
|
||||
deposit,
|
||||
)
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// SimulateMsgDeposit
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
key := simulation.RandomKey(r, keys)
|
||||
addr := sdk.AccAddress(key.PubKey().Address())
|
||||
proposalID, ok := randomProposalID(r, k, ctx)
|
||||
|
@ -61,7 +67,9 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
|||
}
|
||||
deposit := randomDeposit(r)
|
||||
msg := gov.NewMsgDeposit(addr, proposalID, deposit)
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := gov.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -79,7 +87,7 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
|||
|
||||
// SimulateMsgVote
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
key := simulation.RandomKey(r, keys)
|
||||
addr := sdk.AccAddress(key.PubKey().Address())
|
||||
proposalID, ok := randomProposalID(r, k, ctx)
|
||||
|
@ -88,7 +96,9 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.Operation {
|
|||
}
|
||||
option := randomVotingOption(r)
|
||||
msg := gov.NewMsgVote(addr, proposalID, option)
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := gov.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -28,6 +29,26 @@ func Simulate(
|
|||
SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
|
||||
}
|
||||
|
||||
func initChain(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress, setups []RandSetup, app *baseapp.BaseApp,
|
||||
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage) (validators map[string]mockValidator) {
|
||||
res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)})
|
||||
validators = make(map[string]mockValidator)
|
||||
for _, validator := range res.Validators {
|
||||
validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)}
|
||||
}
|
||||
|
||||
for i := 0; i < len(setups); i++ {
|
||||
setups[i](r, keys)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func randTimestamp(r *rand.Rand) time.Time {
|
||||
unixTime := r.Int63n(int64(math.Pow(2, 40)))
|
||||
return time.Unix(unixTime, 0)
|
||||
}
|
||||
|
||||
// SimulateFromSeed tests an application by running the provided
|
||||
// operations, testing the provided invariants, but using the provided seed.
|
||||
func SimulateFromSeed(
|
||||
|
@ -36,11 +57,7 @@ func SimulateFromSeed(
|
|||
) {
|
||||
log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed))
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
|
||||
unixTime := r.Int63n(int64(math.Pow(2, 40)))
|
||||
|
||||
// Set the timestamp for simulation
|
||||
timestamp := time.Unix(unixTime, 0)
|
||||
timestamp := randTimestamp(r)
|
||||
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
|
||||
|
@ -54,30 +71,18 @@ func SimulateFromSeed(
|
|||
events[what]++
|
||||
}
|
||||
|
||||
res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)})
|
||||
validators := make(map[string]mockValidator)
|
||||
for _, validator := range res.Validators {
|
||||
validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)}
|
||||
}
|
||||
|
||||
for i := 0; i < len(setups); i++ {
|
||||
setups[i](r, keys)
|
||||
}
|
||||
validators := initChain(r, keys, accs, setups, app, appStateFn)
|
||||
|
||||
header := abci.Header{Height: 0, Time: timestamp}
|
||||
opCount := 0
|
||||
|
||||
request := abci.RequestBeginBlock{Header: header}
|
||||
|
||||
var pastTimes []time.Time
|
||||
var lastHeaderTime time.Time
|
||||
// These are operations which have been queued by previous operations
|
||||
operationQueue := make(map[int][]Operation)
|
||||
|
||||
for i := 0; i < numBlocks; i++ {
|
||||
|
||||
// Log the header time for future lookup
|
||||
pastTimes = append(pastTimes, header.Time)
|
||||
|
||||
// Run the BeginBlock handler
|
||||
app.BeginBlock(request)
|
||||
|
||||
|
@ -88,16 +93,8 @@ func SimulateFromSeed(
|
|||
|
||||
ctx := app.NewContext(false, header)
|
||||
|
||||
var thisBlockSize int
|
||||
load := r.Float64()
|
||||
switch {
|
||||
case load < 0.33:
|
||||
thisBlockSize = 0
|
||||
case load < 0.66:
|
||||
thisBlockSize = r.Intn(blockSize * 2)
|
||||
default:
|
||||
thisBlockSize = r.Intn(blockSize * 4)
|
||||
}
|
||||
thisBlockSize := getBlockSize(r, blockSize)
|
||||
|
||||
// Run queued operations. Ignores blocksize if blocksize is too small
|
||||
log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), t, r, app, ctx, keys, log, event)
|
||||
opCount += numQueuedOpsRan
|
||||
|
@ -119,6 +116,7 @@ func SimulateFromSeed(
|
|||
|
||||
res := app.EndBlock(abci.RequestEndBlock{})
|
||||
header.Height++
|
||||
lastHeaderTime = header.Time
|
||||
header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second)
|
||||
|
||||
log += "\nEndBlock"
|
||||
|
@ -131,7 +129,7 @@ func SimulateFromSeed(
|
|||
}
|
||||
|
||||
// Generate a random RequestBeginBlock with the current validator set for the next block
|
||||
request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log)
|
||||
request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log)
|
||||
|
||||
// Update the validator set
|
||||
validators = updateValidators(t, r, validators, res.ValidatorUpdates, event)
|
||||
|
@ -141,6 +139,84 @@ func SimulateFromSeed(
|
|||
DisplayEvents(events)
|
||||
}
|
||||
|
||||
func getBlockSize(r *rand.Rand, blockSize int) int {
|
||||
load := r.Float64()
|
||||
switch {
|
||||
case load < 0.33:
|
||||
return 0
|
||||
case load < 0.66:
|
||||
return r.Intn(blockSize * 2)
|
||||
default:
|
||||
return r.Intn(blockSize * 4)
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate from seed, benchmarks
|
||||
func BenchmarkSimulationFromSeed(b *testing.B, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
|
||||
seed int64, ops []Operation, setups []RandSetup, numBlocks int, blockSize int, commit bool) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
timestamp := randTimestamp(r)
|
||||
timeDiff := maxTimePerBlock - minTimePerBlock
|
||||
keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys)
|
||||
|
||||
// Setup event stats
|
||||
events := make(map[string]uint)
|
||||
event := func(what string) {
|
||||
events[what]++
|
||||
}
|
||||
|
||||
validators := initChain(r, keys, accs, setups, app, appStateFn)
|
||||
|
||||
header := abci.Header{Height: 0, Time: timestamp}
|
||||
opCount := 0
|
||||
|
||||
request := abci.RequestBeginBlock{Header: header}
|
||||
|
||||
var lastHeaderTime time.Time
|
||||
// These are operations which have been queued by previous operations
|
||||
operationQueue := make(map[int][]Operation)
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < numBlocks; i++ {
|
||||
|
||||
// Run the BeginBlock handler
|
||||
app.BeginBlock(request)
|
||||
|
||||
ctx := app.NewContext(false, header)
|
||||
|
||||
thisBlockSize := getBlockSize(r, blockSize)
|
||||
|
||||
// Run queued operations. Ignores blocksize if blocksize is too small
|
||||
log, numQueuedOpsRan := runQueuedOperations(operationQueue, int(header.Height), b, r, app, ctx, keys, "", event)
|
||||
opCount += numQueuedOpsRan
|
||||
thisBlockSize -= numQueuedOpsRan
|
||||
for j := 0; j < thisBlockSize; j++ {
|
||||
_, futureOps, err := ops[r.Intn(len(ops))](b, r, app, ctx, keys, "", event)
|
||||
queueOperations(operationQueue, futureOps)
|
||||
if err != nil {
|
||||
b.Fatalf("error on operation %d, %v", opCount, err)
|
||||
}
|
||||
opCount++
|
||||
}
|
||||
|
||||
res := app.EndBlock(abci.RequestEndBlock{})
|
||||
header.Height++
|
||||
lastHeaderTime = header.Time
|
||||
header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second)
|
||||
if commit {
|
||||
app.Commit()
|
||||
}
|
||||
|
||||
// Generate a random RequestBeginBlock with the current validator set for the next block
|
||||
request = RandomRequestBeginBlock(r, validators, livenessTransitionMatrix, evidenceFraction, lastHeaderTime, event, header, log)
|
||||
|
||||
// Update the validator set
|
||||
validators = updateValidators(b, r, validators, res.ValidatorUpdates, event)
|
||||
}
|
||||
DisplayEvents(events)
|
||||
fmt.Printf("Benchmark simulation ran %d operations\n", opCount)
|
||||
}
|
||||
|
||||
// adds all future operations into the operation queue.
|
||||
func queueOperations(queuedOperations map[int][]Operation, futureOperations []FutureOperation) {
|
||||
if futureOperations == nil {
|
||||
|
@ -155,7 +231,7 @@ func queueOperations(queuedOperations map[int][]Operation, futureOperations []Fu
|
|||
}
|
||||
}
|
||||
|
||||
func runQueuedOperations(queueOperations map[int][]Operation, height int, t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
func runQueuedOperations(queueOperations map[int][]Operation, height int, tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
privKeys []crypto.PrivKey, log string, event func(string)) (updatedLog string, numOpsRan int) {
|
||||
updatedLog = log
|
||||
if queuedOps, ok := queueOperations[height]; ok {
|
||||
|
@ -164,9 +240,12 @@ func runQueuedOperations(queueOperations map[int][]Operation, height int, t *tes
|
|||
// For now, queued operations cannot queue more operations.
|
||||
// If a need arises for us to support queued messages to queue more messages, this can
|
||||
// be changed.
|
||||
logUpdate, _, err := queuedOps[i](t, r, app, ctx, privKeys, updatedLog, event)
|
||||
updatedLog += "\n" + logUpdate
|
||||
require.Nil(t, err, updatedLog)
|
||||
logUpdate, _, err := queuedOps[i](tb, r, app, ctx, privKeys, updatedLog, event)
|
||||
updatedLog = fmt.Sprintf("%s\n%s", updatedLog, logUpdate)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, updatedLog)
|
||||
tb.FailNow()
|
||||
}
|
||||
}
|
||||
delete(queueOperations, height)
|
||||
return updatedLog, numOps
|
||||
|
@ -186,8 +265,8 @@ func getKeys(validators map[string]mockValidator) []string {
|
|||
}
|
||||
|
||||
// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators, signing fraction, and evidence fraction
|
||||
func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64,
|
||||
pastTimes []time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock {
|
||||
func RandomRequestBeginBlock(r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64,
|
||||
lastHeaderTime time.Time, event func(string), header abci.Header, log string) abci.RequestBeginBlock {
|
||||
if len(validators) == 0 {
|
||||
return abci.RequestBeginBlock{Header: header}
|
||||
}
|
||||
|
@ -219,13 +298,14 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m
|
|||
}
|
||||
i++
|
||||
}
|
||||
// TODO: Determine capacity before allocation
|
||||
evidence := make([]abci.Evidence, 0)
|
||||
for r.Float64() < evidenceFraction {
|
||||
height := header.Height
|
||||
time := header.Time
|
||||
if r.Float64() < pastEvidenceFraction {
|
||||
height = int64(r.Intn(int(header.Height)))
|
||||
time = pastTimes[height]
|
||||
time = lastHeaderTime
|
||||
}
|
||||
validator := signingValidators[r.Intn(len(signingValidators))].Validator
|
||||
var currentTotalVotingPower int64
|
||||
|
@ -258,11 +338,19 @@ func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant,
|
|||
}
|
||||
|
||||
// updateValidators mimicks Tendermint's update logic
|
||||
func updateValidators(t *testing.T, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator {
|
||||
func updateValidators(tb testing.TB, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator, event func(string)) map[string]mockValidator {
|
||||
for _, update := range updates {
|
||||
switch {
|
||||
case update.Power == 0:
|
||||
require.NotNil(t, current[string(update.PubKey.Data)], "tried to delete a nonexistent validator")
|
||||
// // TEMPORARY DEBUG CODE TO PROVE THAT THE OLD METHOD WAS BROKEN
|
||||
// // (i.e. didn't catch in the event of problem)
|
||||
// if val, ok := tb.(*testing.T); ok {
|
||||
// require.NotNil(val, current[string(update.PubKey.Data)])
|
||||
// }
|
||||
// // CORRECT CHECK
|
||||
// if _, ok := current[string(update.PubKey.Data)]; !ok {
|
||||
// tb.Fatalf("tried to delete a nonexistent validator")
|
||||
// }
|
||||
event("endblock/validatorupdates/kicked")
|
||||
delete(current, string(update.PubKey.Data))
|
||||
default:
|
||||
|
|
|
@ -23,7 +23,7 @@ type (
|
|||
// Operations can optionally provide a list of "FutureOperations" to run later
|
||||
// These will be ran at the beginning of the corresponding block.
|
||||
Operation func(
|
||||
t *testing.T, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
|
||||
privKeys []crypto.PrivKey, log string, event func(string),
|
||||
) (action string, futureOperations []FutureOperation, err sdk.Error)
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
|
@ -17,11 +15,13 @@ import (
|
|||
|
||||
// SimulateMsgUnjail
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
key := simulation.RandomKey(r, keys)
|
||||
address := sdk.AccAddress(key.PubKey().Address())
|
||||
msg := slashing.NewMsgUnjail(address)
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := slashing.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
@ -19,7 +17,7 @@ import (
|
|||
|
||||
// SimulateMsgCreateValidator
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
description := stake.Description{
|
||||
Moniker: simulation.RandStringOfLength(r, 10),
|
||||
|
@ -41,7 +39,9 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation
|
|||
PubKey: pubkey,
|
||||
Delegation: sdk.NewCoin(denom, amount),
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -56,7 +56,7 @@ func SimulateMsgCreateValidator(m auth.AccountMapper, k stake.Keeper) simulation
|
|||
|
||||
// SimulateMsgEditValidator
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
description := stake.Description{
|
||||
Moniker: simulation.RandStringOfLength(r, 10),
|
||||
Identity: simulation.RandStringOfLength(r, 10),
|
||||
|
@ -70,7 +70,9 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
|
|||
Description: description,
|
||||
ValidatorAddr: address,
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -84,7 +86,7 @@ func SimulateMsgEditValidator(k stake.Keeper) simulation.Operation {
|
|||
|
||||
// SimulateMsgDelegate
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
validatorKey := simulation.RandomKey(r, keys)
|
||||
validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address())
|
||||
|
@ -102,7 +104,9 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat
|
|||
ValidatorAddr: validatorAddress,
|
||||
Delegation: sdk.NewCoin(denom, amount),
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -116,7 +120,7 @@ func SimulateMsgDelegate(m auth.AccountMapper, k stake.Keeper) simulation.Operat
|
|||
|
||||
// SimulateMsgBeginUnbonding
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
validatorKey := simulation.RandomKey(r, keys)
|
||||
validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address())
|
||||
|
@ -134,7 +138,9 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
|
|||
ValidatorAddr: validatorAddress,
|
||||
SharesAmount: sdk.NewDecFromInt(amount),
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -148,7 +154,7 @@ func SimulateMsgBeginUnbonding(m auth.AccountMapper, k stake.Keeper) simulation.
|
|||
|
||||
// SimulateMsgCompleteUnbonding
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
validatorKey := simulation.RandomKey(r, keys)
|
||||
validatorAddress := sdk.AccAddress(validatorKey.PubKey().Address())
|
||||
delegatorKey := simulation.RandomKey(r, keys)
|
||||
|
@ -157,7 +163,9 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation {
|
|||
DelegatorAddr: delegatorAddress,
|
||||
ValidatorAddr: validatorAddress,
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -171,7 +179,7 @@ func SimulateMsgCompleteUnbonding(k stake.Keeper) simulation.Operation {
|
|||
|
||||
// SimulateMsgBeginRedelegate
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
denom := k.GetParams(ctx).BondDenom
|
||||
sourceValidatorKey := simulation.RandomKey(r, keys)
|
||||
sourceValidatorAddress := sdk.AccAddress(sourceValidatorKey.PubKey().Address())
|
||||
|
@ -193,7 +201,9 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
|
|||
ValidatorDstAddr: destValidatorAddress,
|
||||
SharesAmount: sdk.NewDecFromInt(amount),
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
@ -207,7 +217,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountMapper, k stake.Keeper) simulation
|
|||
|
||||
// SimulateMsgCompleteRedelegate
|
||||
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, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
return func(tb testing.TB, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, keys []crypto.PrivKey, log string, event func(string)) (action string, fOp []simulation.FutureOperation, err sdk.Error) {
|
||||
validatorSrcKey := simulation.RandomKey(r, keys)
|
||||
validatorSrcAddress := sdk.AccAddress(validatorSrcKey.PubKey().Address())
|
||||
validatorDstKey := simulation.RandomKey(r, keys)
|
||||
|
@ -219,7 +229,9 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.Operation {
|
|||
ValidatorSrcAddr: validatorSrcAddress,
|
||||
ValidatorDstAddr: validatorDstAddress,
|
||||
}
|
||||
require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes())
|
||||
if msg.ValidateBasic() != nil {
|
||||
tb.Fatalf("expected msg to pass ValidateBasic: %s, log %s", msg.GetSignBytes(), log)
|
||||
}
|
||||
ctx, write := ctx.CacheContext()
|
||||
result := stake.NewHandler(k)(ctx, msg)
|
||||
if result.IsOK() {
|
||||
|
|
Loading…
Reference in New Issue