From 15a5cd5390df2eb6de84b158870f6a742cec0c19 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 20 Jul 2018 21:20:46 +0200 Subject: [PATCH 01/63] Simulate time passing --- cmd/gaia/app/sim_test.go | 16 +++++++++++----- x/bank/simulation/sim_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 12 ++++++++---- x/stake/simulation/sim_test.go | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index f0bea1e177fc..34e87ad34383 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -19,11 +19,13 @@ import ( ) var ( - seed int64 - numKeys int - numBlocks int - blockSize int - enabled bool + seed int64 + numKeys int + numBlocks int + blockSize int + minTimePerBlock int64 + maxTimePerBlock int64 + enabled bool ) func init() { @@ -31,6 +33,8 @@ func init() { flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") flag.IntVar(&numBlocks, "SimulationNumBlocks", 100, "Number of blocks") flag.IntVar(&blockSize, "SimulationBlockSize", 100, "Operations per block") + flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 10, "Minimum time per block (seconds)") + flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 20, "Maximum time per block (seconds)") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") } @@ -95,6 +99,8 @@ func TestFullGaiaSimulation(t *testing.T) { numKeys, numBlocks, blockSize, + minTimePerBlock, + maxTimePerBlock, ) } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 5d76dd0589a6..1f51dc69200c 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -39,6 +39,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 100, 30, 30, + 100, 30, 30, 10, 20, ) } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 5f507b89c1fd..95d4cafd2afa 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -17,17 +17,17 @@ import ( // Simulate tests application by sending random messages. func Simulate( t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock) } // 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, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) keys, addrs := mock.GeneratePrivKeyAddressPairs(numKeys) @@ -39,13 +39,16 @@ func SimulateFromSeed( events[what]++ } + time := int64(0) + timeDiff := maxTimePerBlock - minTimePerBlock + app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, addrs)}) for i := 0; i < len(setups); i++ { setups[i](r, keys) } app.Commit() - header := abci.Header{Height: 0} + header := abci.Header{Height: 0, Time: time} for i := 0; i < numBlocks; i++ { app.BeginBlock(abci.RequestBeginBlock{}) @@ -68,6 +71,7 @@ func SimulateFromSeed( app.EndBlock(abci.RequestEndBlock{}) header.Height++ + header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) } DisplayEvents(events) diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 391ca1996e7d..6870d6cf7a41 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -54,6 +54,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, 10, 100, 100, + }, 10, 100, 100, 10, 20, ) } From 2a04c0473007e1199216bfc3bb41dfb63aa86265 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 20 Jul 2018 21:24:43 +0200 Subject: [PATCH 02/63] Print out final height & time --- Makefile | 2 ++ cmd/gaia/app/sim_test.go | 4 ++-- x/mock/simulation/random_simulate_blocks.go | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6459f08e8974..0caa9812bb05 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,8 @@ test_sim: @echo "Pass the flag 'SimulationNumKeys' to run with the specified number of keys." @echo "Pass the flag 'SimulationNumBlocks' to run with the specified number of blocks." @echo "Pass the flag 'SimulationBlockSize' to run with the specified block size (operations per block)." + @echo "Pass the flag 'SimulationMinTimePerBlock' to run with the specified minimum block time." + @echo "Pass the flag 'SimulationMaxTimePerBlock' to run with the specified maximum block time." @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationBlockSize=200 -v test_cover: diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 34e87ad34383..7a48233ba784 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -31,8 +31,8 @@ var ( func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") - flag.IntVar(&numBlocks, "SimulationNumBlocks", 100, "Number of blocks") - flag.IntVar(&blockSize, "SimulationBlockSize", 100, "Operations per block") + flag.IntVar(&numBlocks, "SimulationNumBlocks", 1000, "Number of blocks") + flag.IntVar(&blockSize, "SimulationBlockSize", 10, "Operations per block") flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 10, "Minimum time per block (seconds)") flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 20, "Maximum time per block (seconds)") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 95d4cafd2afa..d0763f122295 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -74,6 +74,7 @@ func SimulateFromSeed( header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) } + fmt.Printf("Simulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) DisplayEvents(events) } From 79e870ad3ee9818b9a67cd1ecf665a5dbe0faea6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Sat, 21 Jul 2018 00:02:00 +0200 Subject: [PATCH 03/63] Simulate validator set changes --- cmd/gaia/app/sim_test.go | 8 +++---- x/mock/simulation/random_simulate_blocks.go | 23 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 7a48233ba784..99a75873741c 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -31,10 +31,10 @@ var ( func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") - flag.IntVar(&numBlocks, "SimulationNumBlocks", 1000, "Number of blocks") - flag.IntVar(&blockSize, "SimulationBlockSize", 10, "Operations per block") - flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 10, "Minimum time per block (seconds)") - flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 20, "Maximum time per block (seconds)") + flag.IntVar(&numBlocks, "SimulationNumBlocks", 50, "Number of blocks") + flag.IntVar(&blockSize, "SimulationBlockSize", 1000, "Operations per block") + flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 60, "Minimum time per block (seconds)") + flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 120, "Maximum time per block (seconds)") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index d0763f122295..f95a524452f5 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -42,7 +42,12 @@ func SimulateFromSeed( time := int64(0) timeDiff := maxTimePerBlock - minTimePerBlock - app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, addrs)}) + res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, addrs)}) + validators := make(map[string]abci.Validator) + for _, validator := range res.Validators { + validators[string(validator.Address)] = validator + } + for i := 0; i < len(setups); i++ { setups[i](r, keys) } @@ -69,7 +74,8 @@ func SimulateFromSeed( AssertAllInvariants(t, app, invariants, log) } - app.EndBlock(abci.RequestEndBlock{}) + res := app.EndBlock(abci.RequestEndBlock{}) + UpdateValidators(t, validators, res.ValidatorUpdates) header.Height++ header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) } @@ -84,3 +90,16 @@ func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, tests[i](t, app, log) } } + +// UpdateValidators mimicks Tendermint's update logic +func UpdateValidators(t *testing.T, current map[string]abci.Validator, updates []abci.Validator) { + for _, update := range updates { + switch { + case update.Power == 0: + require.NotNil(t, current[string(update.Address)], "tried to delete a nonexistent validator") + delete(current, string(update.Address)) + default: + current[string(update.Address)] = update + } + } +} From a1ea7ccb7cb5052808f3ff3aedae6a86c168ff7b Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Sat, 21 Jul 2018 00:06:18 +0200 Subject: [PATCH 04/63] Simulate different block loads --- x/mock/simulation/random_simulate_blocks.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index f95a524452f5..ac073f11e9bc 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -64,9 +64,17 @@ func SimulateFromSeed( ctx := app.NewContext(false, header) - // TODO: Add modes to simulate "no load", "medium load", and - // "high load" blocks. - for j := 0; j < blockSize; j++ { + var thisBlockSize int + load := r.Float64() + switch { + case load < 0.33: + thisBlockSize = 0 + case load < 0.66: + thisBlockSize = blockSize + default: + thisBlockSize = blockSize * 2 + } + for j := 0; j < thisBlockSize; j++ { logUpdate, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) log += "\n" + logUpdate From 9c55ec5a67998f77910757ca8b63846871a69b0b Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 00:07:23 +0200 Subject: [PATCH 05/63] Random SigningValidators --- Makefile | 1 + cmd/gaia/app/sim_test.go | 3 ++ x/bank/simulation/sim_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 32 +++++++++++++++++---- x/stake/simulation/sim_test.go | 2 +- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 6831d2aca0dc..e21eb7d88818 100644 --- a/Makefile +++ b/Makefile @@ -141,6 +141,7 @@ test_sim: @echo "Pass the flag 'SimulationBlockSize' to run with the specified block size (operations per block)." @echo "Pass the flag 'SimulationMinTimePerBlock' to run with the specified minimum block time." @echo "Pass the flag 'SimulationMaxTimePerBlock' to run with the specified maximum block time." + @echo "Pass the flag 'SimulationSigningFraction' to run with the specified chance of a given validator signing a given block." @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationBlockSize=200 -v test_cover: diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 99a75873741c..07dea8a23e56 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -25,6 +25,7 @@ var ( blockSize int minTimePerBlock int64 maxTimePerBlock int64 + signingFraction float64 enabled bool ) @@ -35,6 +36,7 @@ func init() { flag.IntVar(&blockSize, "SimulationBlockSize", 1000, "Operations per block") flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 60, "Minimum time per block (seconds)") flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 120, "Maximum time per block (seconds)") + flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") } @@ -101,6 +103,7 @@ func TestFullGaiaSimulation(t *testing.T) { blockSize, minTimePerBlock, maxTimePerBlock, + signingFraction, ) } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 1f51dc69200c..5db509fa0af0 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -39,6 +39,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 100, 30, 30, 10, 20, + 100, 30, 30, 10, 20, 0.7, ) } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index ac073f11e9bc..db3522da7306 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -17,17 +17,17 @@ import ( // Simulate tests application by sending random messages. func Simulate( t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock, signingFraction) } // 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, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) keys, addrs := mock.GeneratePrivKeyAddressPairs(numKeys) @@ -56,10 +56,12 @@ func SimulateFromSeed( header := abci.Header{Height: 0, Time: time} for i := 0; i < numBlocks; i++ { - app.BeginBlock(abci.RequestBeginBlock{}) - // Make sure invariants hold at beginning of block and when nothing was - // done. + // Generate a random RequestBeginBlock with the current validator set + request := RandomRequestBeginBlock(t, r, validators, signingFraction) + app.BeginBlock(request) + + // Make sure invariants hold at beginning of block AssertAllInvariants(t, app, invariants, log) ctx := app.NewContext(false, header) @@ -92,6 +94,24 @@ func SimulateFromSeed( DisplayEvents(events) } +// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators and signing fraction +func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]abci.Validator, signingFraction float64) abci.RequestBeginBlock { + require.True(t, len(validators) > 0, "Zero validators can't sign a block!") + signingValidators := make([]abci.SigningValidator, len(validators)) + i := 0 + for _, val := range validators { + signed := r.Float64() < signingFraction + signingValidators[i] = abci.SigningValidator{ + Validator: val, + SignedLastBlock: signed, + } + i++ + } + return abci.RequestBeginBlock{ + Validators: signingValidators, + } +} + // AssertAllInvariants asserts a list of provided invariants against application state func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, log string) { for i := 0; i < len(tests); i++ { diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 6870d6cf7a41..7128537c4ecb 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -54,6 +54,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, 10, 100, 100, 10, 20, + }, 10, 100, 100, 10, 20, 0.7, ) } From 782fcd7f4b0217ee5cc2c7d820e283bc3e19c972 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 00:16:47 +0200 Subject: [PATCH 06/63] Simple random Byzantine evidence --- Makefile | 1 + cmd/gaia/app/sim_test.go | 4 ++- x/bank/simulation/sim_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 32 ++++++++++++++++----- x/stake/simulation/sim_test.go | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index e21eb7d88818..a485443d61ec 100644 --- a/Makefile +++ b/Makefile @@ -142,6 +142,7 @@ test_sim: @echo "Pass the flag 'SimulationMinTimePerBlock' to run with the specified minimum block time." @echo "Pass the flag 'SimulationMaxTimePerBlock' to run with the specified maximum block time." @echo "Pass the flag 'SimulationSigningFraction' to run with the specified chance of a given validator signing a given block." + @echo "Pass the flag 'SimulationEvidenceFraction' to run with the specified chance of finding evidence on a given block." @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationBlockSize=200 -v test_cover: diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 07dea8a23e56..f49abdae50b7 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -32,11 +32,12 @@ var ( func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") - flag.IntVar(&numBlocks, "SimulationNumBlocks", 50, "Number of blocks") + flag.IntVar(&numBlocks, "SimulationNumBlocks", 100, "Number of blocks") flag.IntVar(&blockSize, "SimulationBlockSize", 1000, "Operations per block") flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 60, "Minimum time per block (seconds)") flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 120, "Maximum time per block (seconds)") flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") + flag.Float64Var(&evidenceFraction, "SimulationEvidenceFraction", 0.01, "Chance that any evidence is found on a given block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") } @@ -104,6 +105,7 @@ func TestFullGaiaSimulation(t *testing.T) { minTimePerBlock, maxTimePerBlock, signingFraction, + evidenceFraction, ) } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 5db509fa0af0..599695ba7748 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -39,6 +39,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 100, 30, 30, 10, 20, 0.7, + 100, 30, 30, 10, 20, 0.7, 0.0, ) } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index db3522da7306..de6c2542e810 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -17,17 +17,17 @@ import ( // Simulate tests application by sending random messages. func Simulate( t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock, signingFraction) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock, signingFraction, evidenceFraction) } // 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, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []TestAndRunTx, setups []RandSetup, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, + invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) keys, addrs := mock.GeneratePrivKeyAddressPairs(numKeys) @@ -58,7 +58,7 @@ func SimulateFromSeed( for i := 0; i < numBlocks; i++ { // Generate a random RequestBeginBlock with the current validator set - request := RandomRequestBeginBlock(t, r, validators, signingFraction) + request := RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time) app.BeginBlock(request) // Make sure invariants hold at beginning of block @@ -94,8 +94,9 @@ func SimulateFromSeed( DisplayEvents(events) } -// RandomRequestBeginBlock generates a list of signing validators according to the provided list of validators and signing fraction -func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]abci.Validator, signingFraction float64) abci.RequestBeginBlock { +// 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]abci.Validator, signingFraction float64, evidenceFraction float64, + currentHeight int64, currentTime int64) abci.RequestBeginBlock { require.True(t, len(validators) > 0, "Zero validators can't sign a block!") signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 @@ -107,8 +108,25 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]a } i++ } + evidence := make([]abci.Evidence, 0) + if r.Float64() < evidenceFraction { + // TODO Also include past evidence + validator := signingValidators[r.Intn(len(signingValidators))].Validator + var currentTotalVotingPower int64 + for _, val := range validators { + currentTotalVotingPower += val.Power + } + evidence = append(evidence, abci.Evidence{ + Type: "DOUBLE_SIGN", + Validator: validator, + Height: currentHeight, + Time: currentTime, + TotalVotingPower: currentTotalVotingPower, + }) + } return abci.RequestBeginBlock{ - Validators: signingValidators, + Validators: signingValidators, + ByzantineValidators: evidence, } } diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 7128537c4ecb..e3c7ec716dc9 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -54,6 +54,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, 10, 100, 100, 10, 20, 0.7, + }, 10, 100, 100, 10, 20, 0.7, 0.0, ) } From e4d0b1775ddbba0e195f6a157493ec6d68589ef4 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 00:22:16 +0200 Subject: [PATCH 07/63] Option to skip RequestBeginBlock randomization --- cmd/gaia/app/sim_test.go | 17 +++++++++-------- x/bank/simulation/sim_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 8 +++++++- x/stake/simulation/sim_test.go | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index f49abdae50b7..9da29878732a 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -19,14 +19,15 @@ import ( ) var ( - seed int64 - numKeys int - numBlocks int - blockSize int - minTimePerBlock int64 - maxTimePerBlock int64 - signingFraction float64 - enabled bool + seed int64 + numKeys int + numBlocks int + blockSize int + minTimePerBlock int64 + maxTimePerBlock int64 + signingFraction float64 + evidenceFraction float64 + enabled bool ) func init() { diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 599695ba7748..c1b64c5fb6ab 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -39,6 +39,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 100, 30, 30, 10, 20, 0.7, 0.0, + 100, 30, 30, 10, 20, 0.0, 0.0, ) } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index de6c2542e810..a55b8a946a08 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -58,7 +58,13 @@ func SimulateFromSeed( for i := 0; i < numBlocks; i++ { // Generate a random RequestBeginBlock with the current validator set - request := RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time) + var request abci.RequestBeginBlock + if signingFraction == 0.0 { + // No BeginBlock simulation + request = abci.RequestBeginBlock{} + } else { + request = RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time) + } app.BeginBlock(request) // Make sure invariants hold at beginning of block diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index e3c7ec716dc9..16e69df4db9d 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -54,6 +54,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, 10, 100, 100, 10, 20, 0.7, 0.0, + }, 10, 100, 100, 10, 20, 0.0, 0.0, ) } From 0f85d6ce1f7913f6ebfce56f22543b850b5e18e9 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 00:39:23 +0200 Subject: [PATCH 08/63] Initial genesis validator in simulation --- cmd/gaia/app/sim_test.go | 15 +++++++++++---- x/bank/simulation/sim_test.go | 4 +++- x/mock/simulation/random_simulate_blocks.go | 12 +++++++----- x/stake/simulation/sim_test.go | 6 ++++-- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 9da29878732a..29fa59ea737f 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" @@ -42,21 +43,27 @@ func init() { flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") } -func appStateFn(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { +func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { var genesisAccounts []GenesisAccount // Randomly generate some genesis accounts - for _, addr := range accs { + for _, acc := range accs { coins := sdk.Coins{sdk.Coin{"steak", sdk.NewInt(100)}} genesisAccounts = append(genesisAccounts, GenesisAccount{ - Address: addr, + Address: acc, Coins: coins, }) } // Default genesis state stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(1000) + stakeGenesis.Pool.LooseTokens = sdk.NewRat(1100) + validator := stake.NewValidator(accs[0], keys[0].PubKey(), stake.Description{}) + validator.Tokens = sdk.NewRat(100) + validator.DelegatorShares = sdk.NewRat(100) + delegation := stake.Delegation{accs[0], accs[0], sdk.NewRat(100), 0} + stakeGenesis.Validators = []stake.Validator{validator} + stakeGenesis.Bonds = []stake.Delegation{delegation} genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index c1b64c5fb6ab..9e12e57afbfb 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -5,6 +5,8 @@ import ( "math/rand" "testing" + "github.com/tendermint/tendermint/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/mock" @@ -24,7 +26,7 @@ func TestBankWithRandomMessages(t *testing.T) { panic(err) } - appStateFn := func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { + appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) return json.RawMessage("{}") } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index a55b8a946a08..daad114cf74a 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -7,16 +7,18 @@ import ( "testing" "time" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mock" "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" ) // Simulate tests application by sending random messages. func Simulate( - t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, 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 []TestAndRunTx, setups []RandSetup, invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { time := time.Now().UnixNano() @@ -26,11 +28,11 @@ 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, 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 []TestAndRunTx, setups []RandSetup, invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) - keys, addrs := mock.GeneratePrivKeyAddressPairs(numKeys) + keys, accs := mock.GeneratePrivKeyAddressPairs(numKeys) r := rand.New(rand.NewSource(seed)) // Setup event stats @@ -42,7 +44,7 @@ func SimulateFromSeed( time := int64(0) timeDiff := maxTimePerBlock - minTimePerBlock - res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, addrs)}) + res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) validators := make(map[string]abci.Validator) for _, validator := range res.Validators { validators[string(validator.Address)] = validator diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 16e69df4db9d..16efef714a1f 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -5,12 +5,14 @@ import ( "math/rand" "testing" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/mock" "github.com/cosmos/cosmos-sdk/x/mock/simulation" "github.com/cosmos/cosmos-sdk/x/stake" - abci "github.com/tendermint/tendermint/abci/types" ) // TestStakeWithRandomMessages @@ -35,7 +37,7 @@ func TestStakeWithRandomMessages(t *testing.T) { panic(err) } - appStateFn := func(r *rand.Rand, accs []sdk.AccAddress) json.RawMessage { + appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) return json.RawMessage("{}") } From d2709e23f2aa4c53783a6bd1175ebc27f8f8627b Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 00:51:47 +0200 Subject: [PATCH 09/63] Helpful printouts --- x/mock/simulation/random_simulate_blocks.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index daad114cf74a..e0f8d0f4e88e 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -94,6 +94,8 @@ func SimulateFromSeed( res := app.EndBlock(abci.RequestEndBlock{}) UpdateValidators(t, validators, res.ValidatorUpdates) + fmt.Printf("Simulation of block %d with %d operations complete.\n", header.Height, thisBlockSize) + header.Height++ header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) } From 6c07f4aa35863014a25e7d880d2677c70601f21a Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 00:54:21 +0200 Subject: [PATCH 10/63] Better load simulation --- x/mock/simulation/random_simulate_blocks.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e0f8d0f4e88e..e6aa44b7912a 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -80,9 +80,9 @@ func SimulateFromSeed( case load < 0.33: thisBlockSize = 0 case load < 0.66: - thisBlockSize = blockSize + thisBlockSize = r.Intn(blockSize * 2) default: - thisBlockSize = blockSize * 2 + thisBlockSize = r.Intn(blockSize * 4) } for j := 0; j < thisBlockSize; j++ { logUpdate, err := ops[r.Intn(len(ops))](t, r, app, ctx, keys, log, event) From 01264b9c1e9e2effd0c94c1705bdb963140ed0a9 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 01:14:20 +0200 Subject: [PATCH 11/63] Nicer logs --- cmd/gaia/app/sim_test.go | 4 ++-- x/mock/simulation/random_simulate_blocks.go | 6 ++++-- x/mock/simulation/util.go | 12 ++++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 29fa59ea737f..7241bc6c024e 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -36,8 +36,8 @@ func init() { flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") flag.IntVar(&numBlocks, "SimulationNumBlocks", 100, "Number of blocks") flag.IntVar(&blockSize, "SimulationBlockSize", 1000, "Operations per block") - flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 60, "Minimum time per block (seconds)") - flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 120, "Maximum time per block (seconds)") + flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 86400, "Minimum time per block (seconds)") + flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 2*86400, "Maximum time per block (seconds)") flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") flag.Float64Var(&evidenceFraction, "SimulationEvidenceFraction", 0.01, "Chance that any evidence is found on a given block") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e6aa44b7912a..c0b826c50f86 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -56,6 +56,7 @@ func SimulateFromSeed( app.Commit() header := abci.Header{Height: 0, Time: time} + opCount := 0 for i := 0; i < numBlocks; i++ { @@ -90,17 +91,18 @@ func SimulateFromSeed( require.Nil(t, err, log) AssertAllInvariants(t, app, invariants, log) + fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) + opCount++ } res := app.EndBlock(abci.RequestEndBlock{}) UpdateValidators(t, validators, res.ValidatorUpdates) - fmt.Printf("Simulation of block %d with %d operations complete.\n", header.Height, thisBlockSize) header.Height++ header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) } - fmt.Printf("Simulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) + fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) DisplayEvents(events) } diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index 14227a1aef70..a7d9533e8b6e 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -3,6 +3,7 @@ package simulation import ( "fmt" "math/rand" + "sort" crypto "github.com/tendermint/tendermint/crypto" @@ -39,8 +40,15 @@ func RandStringOfLength(r *rand.Rand, n int) string { // Pretty-print events as a table func DisplayEvents(events map[string]uint) { - // TODO - fmt.Printf("Events: %v\n", events) + var keys []string + for key, _ := range events { + keys = append(keys, key) + } + sort.Strings(keys) + fmt.Printf("Event statistics: \n") + for _, key := range keys { + fmt.Printf(" %s\t=>\t%d\n", key, events[key]) + } } // Pick a random key from an array From d7f155395a1a8670eb6dca81ed5b08957e81741f Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 24 Jul 2018 01:28:05 +0200 Subject: [PATCH 12/63] Linter fixes; 'make format' --- x/bank/app_test.go | 24 ++++++++++++------------ x/mock/simulation/util.go | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 8b6968eb9a3f..d8736d0fa5ff 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -112,8 +112,8 @@ func TestMsgSendWithAccounts(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)}}, + {addr1, sdk.Coins{sdk.NewCoin("foocoin", 57)}}, + {addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)}}, }, }, { @@ -168,9 +168,9 @@ func TestMsgSendMultipleOut(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 47)}}, - expectedBalance{addr3, sdk.Coins{sdk.NewCoin("foocoin", 5)}}, + {addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, + {addr2, sdk.Coins{sdk.NewCoin("foocoin", 47)}}, + {addr3, sdk.Coins{sdk.NewCoin("foocoin", 5)}}, }, }, } @@ -210,10 +210,10 @@ func TestSengMsgMultipleInOut(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1, priv4}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, - expectedBalance{addr4, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 52)}}, - expectedBalance{addr3, sdk.Coins{sdk.NewCoin("foocoin", 10)}}, + {addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, + {addr4, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, + {addr2, sdk.Coins{sdk.NewCoin("foocoin", 52)}}, + {addr3, sdk.Coins{sdk.NewCoin("foocoin", 10)}}, }, }, } @@ -245,8 +245,8 @@ func TestMsgSendDependent(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)}}, + {addr1, sdk.Coins{sdk.NewCoin("foocoin", 32)}}, + {addr2, sdk.Coins{sdk.NewCoin("foocoin", 10)}}, }, }, { @@ -256,7 +256,7 @@ func TestMsgSendDependent(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv2}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)}}, + {addr1, sdk.Coins{sdk.NewCoin("foocoin", 42)}}, }, }, } diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index a7d9533e8b6e..8b26bddf246c 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -41,7 +41,7 @@ func RandStringOfLength(r *rand.Rand, n int) string { // Pretty-print events as a table func DisplayEvents(events map[string]uint) { var keys []string - for key, _ := range events { + for key := range events { keys = append(keys, key) } sort.Strings(keys) From 738009c46e78a93e6b8a91d6562dcecae171a885 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 00:09:24 +0200 Subject: [PATCH 13/63] Delay RequestBeginBlock.SigningValidators one block; nicer formatting --- x/mock/simulation/random_simulate_blocks.go | 24 ++++++++++++--------- x/mock/simulation/util.go | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index c0b826c50f86..c03a165f6359 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -58,16 +58,11 @@ func SimulateFromSeed( header := abci.Header{Height: 0, Time: time} opCount := 0 + request := abci.RequestBeginBlock{} + for i := 0; i < numBlocks; i++ { - // Generate a random RequestBeginBlock with the current validator set - var request abci.RequestBeginBlock - if signingFraction == 0.0 { - // No BeginBlock simulation - request = abci.RequestBeginBlock{} - } else { - request = RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time) - } + // Run the BeginBlock handler app.BeginBlock(request) // Make sure invariants hold at beginning of block @@ -96,10 +91,19 @@ func SimulateFromSeed( } res := app.EndBlock(abci.RequestEndBlock{}) - UpdateValidators(t, validators, res.ValidatorUpdates) - header.Height++ header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) + + // Generate a random RequestBeginBlock with the current validator set for the next block + if signingFraction == 0.0 { + // No BeginBlock simulation + request = abci.RequestBeginBlock{} + } else { + request = RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time) + } + + // Update the validator set + UpdateValidators(t, validators, res.ValidatorUpdates) } fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index 8b26bddf246c..d95b1d12419f 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -47,7 +47,7 @@ func DisplayEvents(events map[string]uint) { sort.Strings(keys) fmt.Printf("Event statistics: \n") for _, key := range keys { - fmt.Printf(" %s\t=>\t%d\n", key, events[key]) + fmt.Printf("\t% 60s => %d\n", key, events[key]) } } From b032b8e945443dec19c7e2c666e5876580e42115 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 01:31:31 +0200 Subject: [PATCH 14/63] Period invariant checks --- Makefile | 2 +- cmd/gaia/app/sim_test.go | 12 ++++++++---- x/gov/simulation/invariants.go | 16 ++++++++++++++++ x/mock/simulation/util.go | 2 +- x/slashing/simulation/invariants.go | 16 ++++++++++++++++ 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 x/gov/simulation/invariants.go create mode 100644 x/slashing/simulation/invariants.go diff --git a/Makefile b/Makefile index a485443d61ec..32485c5d9120 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,7 @@ test_sim: @echo "Pass the flag 'SimulationMaxTimePerBlock' to run with the specified maximum block time." @echo "Pass the flag 'SimulationSigningFraction' to run with the specified chance of a given validator signing a given block." @echo "Pass the flag 'SimulationEvidenceFraction' to run with the specified chance of finding evidence on a given block." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationBlockSize=200 -v + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -v test_cover: @bash tests/test_cover.sh diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 7241bc6c024e..c6fad22aefe6 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -14,7 +14,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" + govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation" "github.com/cosmos/cosmos-sdk/x/mock/simulation" + slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation" stake "github.com/cosmos/cosmos-sdk/x/stake" stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation" ) @@ -34,8 +36,8 @@ var ( func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") - flag.IntVar(&numBlocks, "SimulationNumBlocks", 100, "Number of blocks") - flag.IntVar(&blockSize, "SimulationBlockSize", 1000, "Operations per block") + flag.IntVar(&numBlocks, "SimulationNumBlocks", 1000, "Number of blocks") + flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 86400, "Minimum time per block (seconds)") flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 2*86400, "Maximum time per block (seconds)") flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") @@ -104,8 +106,10 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - banksim.NonnegativeBalanceInvariant(app.accountMapper), - stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper), + simulation.PeriodicInvariant(banksim.NonnegativeBalanceInvariant(app.accountMapper), 100, 0), + simulation.PeriodicInvariant(govsim.AllInvariants(), 100, 0), + simulation.PeriodicInvariant(stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper), 100, 0), + simulation.PeriodicInvariant(slashingsim.AllInvariants(), 100, 0), }, numKeys, numBlocks, diff --git a/x/gov/simulation/invariants.go b/x/gov/simulation/invariants.go new file mode 100644 index 000000000000..479fe69472b7 --- /dev/null +++ b/x/gov/simulation/invariants.go @@ -0,0 +1,16 @@ +package simulation + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" +) + +func AllInvariants() simulation.Invariant { + return func(t *testing.T, app *baseapp.BaseApp, log string) { + require.Nil(t, nil) + } +} diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index d95b1d12419f..e2983168a417 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -47,7 +47,7 @@ func DisplayEvents(events map[string]uint) { sort.Strings(keys) fmt.Printf("Event statistics: \n") for _, key := range keys { - fmt.Printf("\t% 60s => %d\n", key, events[key]) + fmt.Printf(" % 60s => %d\n", key, events[key]) } } diff --git a/x/slashing/simulation/invariants.go b/x/slashing/simulation/invariants.go new file mode 100644 index 000000000000..479fe69472b7 --- /dev/null +++ b/x/slashing/simulation/invariants.go @@ -0,0 +1,16 @@ +package simulation + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" +) + +func AllInvariants() simulation.Invariant { + return func(t *testing.T, app *baseapp.BaseApp, log string) { + require.Nil(t, nil) + } +} From 2bf2c9a94d0030af407706afd14532145375bb99 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 01:55:12 +0200 Subject: [PATCH 15/63] SimulateMsgUnrevoke --- cmd/gaia/app/sim_test.go | 1 + x/slashing/simulation/msgs.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 x/slashing/simulation/msgs.go diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index c6fad22aefe6..b5ff2fdb52b0 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -103,6 +103,7 @@ func TestFullGaiaSimulation(t *testing.T) { stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), + slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), }, []simulation.RandSetup{}, []simulation.Invariant{ diff --git a/x/slashing/simulation/msgs.go b/x/slashing/simulation/msgs.go new file mode 100644 index 000000000000..b6a093674b6b --- /dev/null +++ b/x/slashing/simulation/msgs.go @@ -0,0 +1,34 @@ +package simulation + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/slashing" +) + +// SimulateMsgUnrevoke +func SimulateMsgUnrevoke(k slashing.Keeper) simulation.TestAndRunTx { + 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()) + msg := slashing.NewMsgUnrevoke(address) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := slashing.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + event(fmt.Sprintf("slashing/MsgUnrevoke/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgUnrevoke: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} From e69f7fcc3dd15fa0ece4ed6e75c3d8dd6fea2571 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 02:33:27 +0200 Subject: [PATCH 16/63] Simulated x/gov msgs, more initially bonded --- cmd/gaia/app/sim_test.go | 28 +++++++++----- x/bank/simulation/msgs.go | 4 ++ x/gov/simulation/msgs.go | 78 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 x/gov/simulation/msgs.go diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index b5ff2fdb52b0..0207f0767cef 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -35,7 +35,7 @@ var ( func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") - flag.IntVar(&numKeys, "SimulationNumKeys", 10, "Number of keys (accounts)") + flag.IntVar(&numKeys, "SimulationNumKeys", 1000, "Number of keys (accounts)") flag.IntVar(&numBlocks, "SimulationNumBlocks", 1000, "Number of blocks") flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 86400, "Minimum time per block (seconds)") @@ -59,13 +59,20 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json // Default genesis state stakeGenesis := stake.DefaultGenesisState() - stakeGenesis.Pool.LooseTokens = sdk.NewRat(1100) - validator := stake.NewValidator(accs[0], keys[0].PubKey(), stake.Description{}) - validator.Tokens = sdk.NewRat(100) - validator.DelegatorShares = sdk.NewRat(100) - delegation := stake.Delegation{accs[0], accs[0], sdk.NewRat(100), 0} - stakeGenesis.Validators = []stake.Validator{validator} - stakeGenesis.Bonds = []stake.Delegation{delegation} + var validators []stake.Validator + var delegations []stake.Delegation + numInitiallyBonded := int64(50) + for i := 0; i < int(numInitiallyBonded); i++ { + validator := stake.NewValidator(accs[i], keys[i].PubKey(), stake.Description{}) + validator.Tokens = sdk.NewRat(100) + validator.DelegatorShares = sdk.NewRat(100) + delegation := stake.Delegation{accs[i], accs[i], sdk.NewRat(100), 0} + validators = append(validators, validator) + delegations = append(delegations, delegation) + } + stakeGenesis.Pool.LooseTokens = sdk.NewRat(int64(100*numKeys) + (numInitiallyBonded * 100)) + stakeGenesis.Validators = validators + stakeGenesis.Bonds = delegations genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, @@ -96,10 +103,13 @@ func TestFullGaiaSimulation(t *testing.T) { t, app.BaseApp, appStateFn, seed, []simulation.TestAndRunTx{ banksim.TestAndRunSingleInputMsgSend(app.accountMapper), + govsim.SimulateMsgSubmitProposal(app.govKeeper), + govsim.SimulateMsgDeposit(app.govKeeper), + govsim.SimulateMsgVote(app.govKeeper), stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgEditValidator(app.stakeKeeper), stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), + //stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), diff --git a/x/bank/simulation/msgs.go b/x/bank/simulation/msgs.go index 3a72488757ed..43d7e1fd7094 100644 --- a/x/bank/simulation/msgs.go +++ b/x/bank/simulation/msgs.go @@ -35,6 +35,10 @@ func TestAndRunSingleInputMsgSend(mapper auth.AccountMapper) simulation.TestAndR toAddr := sdk.AccAddress(toKey.PubKey().Address()) initFromCoins := mapper.GetAccount(ctx, fromAddr).GetCoins() + if len(initFromCoins) == 0 { + return "skipping, no coins at all", nil + } + denomIndex := r.Intn(len(initFromCoins)) amt, goErr := randPositiveInt(r, initFromCoins[denomIndex].Amount) if goErr != nil { diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go new file mode 100644 index 000000000000..0f84ba3e379d --- /dev/null +++ b/x/gov/simulation/msgs.go @@ -0,0 +1,78 @@ +package simulation + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" +) + +// SimulateMsgSubmitProposal +func SimulateMsgSubmitProposal(k gov.Keeper) simulation.TestAndRunTx { + 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()) + deposit := sdk.Coins{sdk.NewCoin("steak", 10)} + msg := gov.NewMsgSubmitProposal( + simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 10), + gov.ProposalTypeText, + addr, + deposit, + ) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := gov.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + event(fmt.Sprintf("gov/MsgSubmitProposal/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgSubmitProposal: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgDeposit +func SimulateMsgDeposit(k gov.Keeper) simulation.TestAndRunTx { + 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()) + deposit := sdk.Coins{sdk.NewCoin("steak", 10)} + msg := gov.NewMsgDeposit(addr, int64(1), deposit) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := gov.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgDeposit: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} + +// SimulateMsgVote +func SimulateMsgVote(k gov.Keeper) simulation.TestAndRunTx { + 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()) + msg := gov.NewMsgVote(addr, int64(1), gov.OptionYes) + require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) + ctx, write := ctx.CacheContext() + result := gov.NewHandler(k)(ctx, msg) + if result.IsOK() { + write() + } + event(fmt.Sprintf("gov/MsgVote/%v", result.IsOK())) + action = fmt.Sprintf("TestMsgVote: ok %v, msg %s", result.IsOK(), msg.GetSignBytes()) + return action, nil + } +} From 9a07c074e9eb20509ad4cbf58ad8dd1a03c750ad Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 03:47:47 +0200 Subject: [PATCH 17/63] Linter fixes; 'make format' --- docs/sdk/core/examples/app2_test.go | 24 +++++++-------- docs/sdk/core/examples/app3.go | 4 +-- docs/sdk/core/examples/app4_test.go | 47 ++++++++++++++--------------- x/gov/simulation/invariants.go | 1 + x/slashing/simulation/invariants.go | 1 + 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/docs/sdk/core/examples/app2_test.go b/docs/sdk/core/examples/app2_test.go index 58a71eb475ab..52d177675bbe 100644 --- a/docs/sdk/core/examples/app2_test.go +++ b/docs/sdk/core/examples/app2_test.go @@ -1,9 +1,9 @@ package app import ( - "testing" - "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto" + "testing" "github.com/stretchr/testify/require" ) @@ -17,8 +17,8 @@ func TestEncoding(t *testing.T) { addr2 := priv2.PubKey().Address().Bytes() sendMsg := MsgSend{ - From: addr1, - To: addr2, + From: addr1, + To: addr2, Amount: sdk.Coins{{"testCoins", sdk.NewInt(100)}}, } @@ -30,8 +30,8 @@ func TestEncoding(t *testing.T) { } sendTxBefore := app2Tx{ - Msg: sendMsg, - PubKey: priv1.PubKey(), + Msg: sendMsg, + PubKey: priv1.PubKey(), Signature: sig, } @@ -47,13 +47,13 @@ func TestEncoding(t *testing.T) { require.Nil(t, err, "Error decoding sendTx") sendTxAfter := tx1.(app2Tx) - + require.Equal(t, sendTxBefore, sendTxAfter, "Transaction changed after encoding/decoding") issueMsg := MsgIssue{ - Issuer: addr1, + Issuer: addr1, Receiver: addr2, - Coin: sdk.Coin{"testCoin", sdk.NewInt(100)}, + Coin: sdk.Coin{"testCoin", sdk.NewInt(100)}, } signBytes = issueMsg.GetSignBytes() @@ -63,8 +63,8 @@ func TestEncoding(t *testing.T) { } issueTxBefore := app2Tx{ - Msg: issueMsg, - PubKey: priv1.PubKey(), + Msg: issueMsg, + PubKey: priv1.PubKey(), Signature: sig, } @@ -80,4 +80,4 @@ func TestEncoding(t *testing.T) { require.Equal(t, issueTxBefore, issueTxAfter, "Transaction changed after encoding/decoding") -} \ No newline at end of file +} diff --git a/docs/sdk/core/examples/app3.go b/docs/sdk/core/examples/app3.go index 009d22300ec7..0974908fa6ab 100644 --- a/docs/sdk/core/examples/app3.go +++ b/docs/sdk/core/examples/app3.go @@ -1,16 +1,16 @@ package app import ( + "github.com/tendermint/tendermint/crypto" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/crypto" bapp "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/wire" ) const ( diff --git a/docs/sdk/core/examples/app4_test.go b/docs/sdk/core/examples/app4_test.go index 4b2de7a779e1..cf2829ec1142 100644 --- a/docs/sdk/core/examples/app4_test.go +++ b/docs/sdk/core/examples/app4_test.go @@ -1,14 +1,14 @@ package app import ( - "github.com/stretchr/testify/require" - "os" "encoding/json" - "testing" - dbm "github.com/tendermint/tendermint/libs/db" - "github.com/tendermint/tendermint/libs/log" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" + dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/libs/log" + "os" + "testing" bapp "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -44,7 +44,7 @@ func InitTestChain(bc *bapp.BaseApp, chainID string, addrs ...sdk.AccAddress) { // Generate basic SpendMsg with one input and output func GenerateSpendMsg(sender, receiver sdk.AccAddress, amount sdk.Coins) bank.MsgSend { return bank.MsgSend{ - Inputs: []bank.Input{{sender, amount}}, + Inputs: []bank.Input{{sender, amount}}, Outputs: []bank.Output{{receiver, amount}}, } } @@ -64,7 +64,7 @@ func TestBadMsg(t *testing.T) { // Construct transaction fee := auth.StdFee{ - Gas: 1000000000000000, + Gas: 1000000000000000, Amount: sdk.Coins{{"testCoin", sdk.NewInt(0)}}, } signBytes := auth.StdSignBytes("test-chain", 0, 0, fee, []sdk.Msg{msg}, "") @@ -72,18 +72,18 @@ func TestBadMsg(t *testing.T) { if err != nil { panic(err) } - sigs := []auth.StdSignature{auth.StdSignature{ - PubKey: priv1.PubKey(), - Signature: sig, + sigs := []auth.StdSignature{{ + PubKey: priv1.PubKey(), + Signature: sig, AccountNumber: 0, - Sequence: 0, + Sequence: 0, }} tx := auth.StdTx{ - Msgs: []sdk.Msg{msg}, - Fee: fee, + Msgs: []sdk.Msg{msg}, + Fee: fee, Signatures: sigs, - Memo: "", + Memo: "", } bc.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{ChainID: "test-chain"}}) @@ -110,7 +110,7 @@ func TestMsgSend(t *testing.T) { msg := GenerateSpendMsg(addr1, addr2, sdk.Coins{{"testCoin", sdk.NewInt(100)}}) fee := auth.StdFee{ - Gas: 1000000000000000, + Gas: 1000000000000000, Amount: sdk.Coins{{"testCoin", sdk.NewInt(0)}}, } signBytes := auth.StdSignBytes("test-chain", 0, 0, fee, []sdk.Msg{msg}, "") @@ -118,18 +118,18 @@ func TestMsgSend(t *testing.T) { if err != nil { panic(err) } - sigs := []auth.StdSignature{auth.StdSignature{ - PubKey: priv1.PubKey(), - Signature: sig, + sigs := []auth.StdSignature{{ + PubKey: priv1.PubKey(), + Signature: sig, AccountNumber: 0, - Sequence: 0, + Sequence: 0, }} tx := auth.StdTx{ - Msgs: []sdk.Msg{msg}, - Fee: fee, + Msgs: []sdk.Msg{msg}, + Fee: fee, Signatures: sigs, - Memo: "", + Memo: "", } bc.BeginBlock(abci.RequestBeginBlock{}) @@ -138,5 +138,4 @@ func TestMsgSend(t *testing.T) { require.True(t, res.IsOK(), res.Log) - -} \ No newline at end of file +} diff --git a/x/gov/simulation/invariants.go b/x/gov/simulation/invariants.go index 479fe69472b7..a958de26a00e 100644 --- a/x/gov/simulation/invariants.go +++ b/x/gov/simulation/invariants.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/mock/simulation" ) +// AllInvariants tests all governance invariants func AllInvariants() simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { require.Nil(t, nil) diff --git a/x/slashing/simulation/invariants.go b/x/slashing/simulation/invariants.go index 479fe69472b7..f2c65d9e3da3 100644 --- a/x/slashing/simulation/invariants.go +++ b/x/slashing/simulation/invariants.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/mock/simulation" ) +// AllInvariants tests all slashing invariants func AllInvariants() simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { require.Nil(t, nil) From be70a2172bde4e019acb4fe656869e603ae65b51 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 05:31:20 +0200 Subject: [PATCH 18/63] Somehow nondeterministic --- cmd/gaia/app/sim_test.go | 19 ++++++++++++------- x/gov/simulation/msgs.go | 13 ++++++++++--- x/mock/simulation/random_simulate_blocks.go | 6 ++++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 0207f0767cef..a220a1db7f22 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -12,6 +12,7 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation" govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation" @@ -98,14 +99,21 @@ func TestFullGaiaSimulation(t *testing.T) { app := NewGaiaApp(logger, db, nil) require.Equal(t, "GaiaApp", app.Name()) + allInvariants := func(t *testing.T, baseapp *baseapp.BaseApp, log string) { + banksim.NonnegativeBalanceInvariant(app.accountMapper)(t, baseapp, log) + govsim.AllInvariants()(t, baseapp, log) + stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper)(t, baseapp, log) + slashingsim.AllInvariants()(t, baseapp, log) + } + // Run randomized simulation simulation.SimulateFromSeed( t, app.BaseApp, appStateFn, seed, []simulation.TestAndRunTx{ banksim.TestAndRunSingleInputMsgSend(app.accountMapper), - govsim.SimulateMsgSubmitProposal(app.govKeeper), - govsim.SimulateMsgDeposit(app.govKeeper), - govsim.SimulateMsgVote(app.govKeeper), + govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), + govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgEditValidator(app.stakeKeeper), stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), @@ -117,10 +125,7 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - simulation.PeriodicInvariant(banksim.NonnegativeBalanceInvariant(app.accountMapper), 100, 0), - simulation.PeriodicInvariant(govsim.AllInvariants(), 100, 0), - simulation.PeriodicInvariant(stakesim.AllInvariants(app.coinKeeper, app.stakeKeeper, app.accountMapper), 100, 0), - simulation.PeriodicInvariant(slashingsim.AllInvariants(), 100, 0), + allInvariants, }, numKeys, numBlocks, diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 0f84ba3e379d..7c81cb0180c2 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -13,10 +13,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov" "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/stake" ) // SimulateMsgSubmitProposal -func SimulateMsgSubmitProposal(k gov.Keeper) simulation.TestAndRunTx { +func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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()) @@ -30,6 +31,9 @@ func SimulateMsgSubmitProposal(k gov.Keeper) simulation.TestAndRunTx { ) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRat(10)) + sk.SetPool(ctx, pool) result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { write() @@ -41,7 +45,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper) simulation.TestAndRunTx { } // SimulateMsgDeposit -func SimulateMsgDeposit(k gov.Keeper) simulation.TestAndRunTx { +func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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,6 +54,9 @@ func SimulateMsgDeposit(k gov.Keeper) simulation.TestAndRunTx { require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRat(10)) + sk.SetPool(ctx, pool) if result.IsOK() { write() } @@ -60,7 +67,7 @@ func SimulateMsgDeposit(k gov.Keeper) simulation.TestAndRunTx { } // SimulateMsgVote -func SimulateMsgVote(k gov.Keeper) simulation.TestAndRunTx { +func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index c03a165f6359..f9270c12718f 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -32,6 +32,7 @@ func SimulateFromSeed( invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) + fmt.Printf("%s\n", log) keys, accs := mock.GeneratePrivKeyAddressPairs(numKeys) r := rand.New(rand.NewSource(seed)) @@ -99,10 +100,11 @@ func SimulateFromSeed( // No BeginBlock simulation request = abci.RequestBeginBlock{} } else { - request = RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time) + request = RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time, log) } // Update the validator set + fmt.Printf("\nUpdates: %v\n", res.ValidatorUpdates) UpdateValidators(t, validators, res.ValidatorUpdates) } @@ -112,7 +114,7 @@ func SimulateFromSeed( // 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]abci.Validator, signingFraction float64, evidenceFraction float64, - currentHeight int64, currentTime int64) abci.RequestBeginBlock { + currentHeight int64, currentTime int64, log string) abci.RequestBeginBlock { require.True(t, len(validators) > 0, "Zero validators can't sign a block!") signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 From d15198888354848c22ca8f2a55f25b86a48875d7 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 06:37:57 +0200 Subject: [PATCH 19/63] Debugging contd. --- x/mock/simulation/random_simulate_blocks.go | 7 +++++-- x/stake/handler.go | 3 +++ x/stake/keeper/validator.go | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index f9270c12718f..d5cc0a0181f5 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -105,7 +105,9 @@ func SimulateFromSeed( // Update the validator set fmt.Printf("\nUpdates: %v\n", res.ValidatorUpdates) - UpdateValidators(t, validators, res.ValidatorUpdates) + fmt.Printf("Len before: %d\n", len(validators)) + validators = UpdateValidators(t, validators, res.ValidatorUpdates) + fmt.Printf("Len after: %d\n", len(validators)) } fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) @@ -156,7 +158,7 @@ func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, } // UpdateValidators mimicks Tendermint's update logic -func UpdateValidators(t *testing.T, current map[string]abci.Validator, updates []abci.Validator) { +func UpdateValidators(t *testing.T, current map[string]abci.Validator, updates []abci.Validator) map[string]abci.Validator { for _, update := range updates { switch { case update.Power == 0: @@ -166,4 +168,5 @@ func UpdateValidators(t *testing.T, current map[string]abci.Validator, updates [ current[string(update.Address)] = update } } + return current } diff --git a/x/stake/handler.go b/x/stake/handler.go index 3cc122e4ca1c..b6f52473f1ad 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -1,6 +1,8 @@ package stake import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/keeper" "github.com/cosmos/cosmos-sdk/x/stake/tags" @@ -10,6 +12,7 @@ import ( func NewHandler(k keeper.Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + fmt.Printf("\nHandling msg %s\n", msg.GetSignBytes()) // NOTE msg already has validate basic run switch msg := msg.(type) { case types.MsgCreateValidator: diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index c7ae43cbebc1..de88e04e585d 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -479,6 +479,8 @@ func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) { // perform all the store operations for when a validator status becomes unbonded func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) types.Validator { + fmt.Printf("\nUnbonding validator: %s\n", validator.Owner) + store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) @@ -506,6 +508,8 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // perform all the store operations for when a validator status becomes bonded func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.Validator { + fmt.Printf("\nBonding validator: %s\n", validator.Owner) + store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) From 50583790b7994c4f8ab5247de7c78e4a913790ae Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 25 Jul 2018 19:47:29 +0200 Subject: [PATCH 20/63] Fix nondeterminism but now we found a bug! --- cmd/gaia/app/sim_test.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 9 +++------ x/stake/handler.go | 3 --- x/stake/keeper/validator.go | 4 ---- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index a220a1db7f22..fc19feff149d 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -125,7 +125,7 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - allInvariants, + simulation.PeriodicInvariant(allInvariants, 100, 0), }, numKeys, numBlocks, diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index d5cc0a0181f5..e8c80c08bb78 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -104,10 +104,7 @@ func SimulateFromSeed( } // Update the validator set - fmt.Printf("\nUpdates: %v\n", res.ValidatorUpdates) - fmt.Printf("Len before: %d\n", len(validators)) validators = UpdateValidators(t, validators, res.ValidatorUpdates) - fmt.Printf("Len after: %d\n", len(validators)) } fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) @@ -162,10 +159,10 @@ func UpdateValidators(t *testing.T, current map[string]abci.Validator, updates [ for _, update := range updates { switch { case update.Power == 0: - require.NotNil(t, current[string(update.Address)], "tried to delete a nonexistent validator") - delete(current, string(update.Address)) + require.NotNil(t, current[string(update.PubKey.Data)], "tried to delete a nonexistent validator") + delete(current, string(update.PubKey.Data)) default: - current[string(update.Address)] = update + current[string(update.PubKey.Data)] = update } } return current diff --git a/x/stake/handler.go b/x/stake/handler.go index b6f52473f1ad..3cc122e4ca1c 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -1,8 +1,6 @@ package stake import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/keeper" "github.com/cosmos/cosmos-sdk/x/stake/tags" @@ -12,7 +10,6 @@ import ( func NewHandler(k keeper.Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - fmt.Printf("\nHandling msg %s\n", msg.GetSignBytes()) // NOTE msg already has validate basic run switch msg := msg.(type) { case types.MsgCreateValidator: diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index de88e04e585d..c7ae43cbebc1 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -479,8 +479,6 @@ func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) { // perform all the store operations for when a validator status becomes unbonded func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) types.Validator { - fmt.Printf("\nUnbonding validator: %s\n", validator.Owner) - store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) @@ -508,8 +506,6 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // perform all the store operations for when a validator status becomes bonded func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.Validator { - fmt.Printf("\nBonding validator: %s\n", validator.Owner) - store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) From 8cacb9658402d7c800e24e3f9f93f7d9576a1d75 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 26 Jul 2018 20:06:10 +0200 Subject: [PATCH 21/63] Debugging contd. --- cmd/gaia/app/sim_test.go | 3 ++- x/stake/keeper/validator.go | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index fc19feff149d..2a58c04b6e0a 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -125,7 +125,8 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - simulation.PeriodicInvariant(allInvariants, 100, 0), + // simulation.PeriodicInvariant(allInvariants, 100, 0), + allInvariants, }, numKeys, numBlocks, diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index c7ae43cbebc1..1d86851686a1 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -339,6 +339,7 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, // validator provided because it has not yet been updated in the store ownerAddr := iterator.Value() if bytes.Equal(ownerAddr, affectedValidator.Owner) { + fmt.Printf("\nAffected validator: %s\n", affectedValidator) validator = affectedValidator } else { var found bool @@ -365,10 +366,16 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, } iterator.Close() + if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Owner) { + panic("cliff validator has not been changed, yet we bonded a new validator") + } + // clear or set the cliff validator if bondedValidatorsCount == int(maxValidators) { + fmt.Printf("Setting cliff validator: %s\n", validator) k.setCliffValidator(ctx, validator, k.GetPool(ctx)) } else if len(oldCliffValidatorAddr) > 0 { + fmt.Printf("Clearing cliff validator\n") k.clearCliffValidator(ctx) } @@ -381,6 +388,8 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr)) } + fmt.Printf("Unbonding old cliff validator: %s\n", cliffVal) + fmt.Printf("Then bonding new validator: %s\n", validatorToBond) k.unbondValidator(ctx, cliffVal) } @@ -484,7 +493,7 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // sanity check if validator.Status == sdk.Unbonded { - panic(fmt.Sprintf("should not already be unbonded, validator: %v\n", validator)) + panic(fmt.Sprintf("should not already be unbonded, validator: %s\n", validator)) } // set the status @@ -511,7 +520,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // sanity check if validator.Status == sdk.Bonded { - panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator)) + panic(fmt.Sprintf("should not already be bonded, validator: %s\n", validator)) } // set the status From 7a02762b627743ee3b5d5024119538e617a4dca3 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 27 Jul 2018 01:06:00 +0200 Subject: [PATCH 22/63] More debugging --- x/stake/keeper/validator.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 1d86851686a1..c5ab568abc78 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -320,6 +320,8 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato func (k Keeper) UpdateBondedValidators(ctx sdk.Context, affectedValidator types.Validator) (updatedVal types.Validator, updated bool) { + fmt.Printf("\nCalling UpdateBondedValidators with %s\n", affectedValidator) + store := ctx.KVStore(k.storeKey) oldCliffValidatorAddr := k.GetCliffValidator(ctx) @@ -339,7 +341,7 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, // validator provided because it has not yet been updated in the store ownerAddr := iterator.Value() if bytes.Equal(ownerAddr, affectedValidator.Owner) { - fmt.Printf("\nAffected validator: %s\n", affectedValidator) + fmt.Printf("Affected validator: %s\n", affectedValidator) validator = affectedValidator } else { var found bool @@ -362,6 +364,8 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr)) } + fmt.Printf("Iter; on validator: %s\n", validator) + iterator.Next() } iterator.Close() From ce522537ba9dc1af5ad1d9852dc434de5c8a2087 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 27 Jul 2018 19:56:34 +0200 Subject: [PATCH 23/63] Debugging contd. --- x/stake/genesis.go | 3 +-- x/stake/keeper/validator.go | 12 +++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/x/stake/genesis.go b/x/stake/genesis.go index ad3ac0af5ab2..7a004bccd270 100644 --- a/x/stake/genesis.go +++ b/x/stake/genesis.go @@ -21,6 +21,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ keeper.InitIntraTxCounter(ctx) for i, validator := range data.Validators { + validator.BondIntraTxCounter = int16(i) // set the intra-tx counter to the order the validators are presented keeper.SetValidator(ctx, validator) if validator.Tokens.IsZero() { @@ -32,8 +33,6 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [ // Manually set indexes for the first time keeper.SetValidatorByPubKeyIndex(ctx, validator) - - validator.BondIntraTxCounter = int16(i) // set the intra-tx counter to the order the validators are presented keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool) if validator.Status == sdk.Bonded { diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index c5ab568abc78..b2d025035e16 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -206,6 +206,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type validator = k.updateForRevoking(ctx, oldFound, oldValidator, validator) powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator) validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator, validator) + fmt.Printf("Found validator: %v, bond height: %v, counter: %v, old bond height: %v, old counter: %v\n", oldFound, validator.BondHeight, validator.BondIntraTxCounter, oldValidator.BondHeight, oldValidator.BondIntraTxCounter) valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool) cliffPower := k.GetCliffValidatorPower(ctx) @@ -295,8 +296,10 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato // update the list ordered by voting power if oldFound { + fmt.Printf("Delete old key: %X\n", GetValidatorsByPowerIndexKey(oldValidator, pool)) store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool)) } + fmt.Printf("Write new key: %X\n", GetValidatorsByPowerIndexKey(newValidator, pool)) valPower = GetValidatorsByPowerIndexKey(newValidator, pool) store.Set(valPower, newValidator.Owner) @@ -330,6 +333,8 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, var validator, validatorToBond types.Validator newValidatorBonded := false + seen := make(map[string]bool) + iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) // largest to smallest for { if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) { @@ -364,7 +369,12 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr)) } - fmt.Printf("Iter; on validator: %s\n", validator) + fmt.Printf("Iter; on key %X, validator: %s\n", iterator.Key(), validator) + + if seen[string(ownerAddr)] { + panic(fmt.Sprintf("duplicate validator: %s", sdk.AccAddress(ownerAddr))) + } + seen[string(ownerAddr)] = true iterator.Next() } From 529b93ace2cff34dc59e53181e23c22107ce94c6 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 27 Jul 2018 23:25:55 +0200 Subject: [PATCH 24/63] Remove debugging Printfs --- x/stake/keeper/validator.go | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index b2d025035e16..597e665a56e6 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -206,7 +206,6 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type validator = k.updateForRevoking(ctx, oldFound, oldValidator, validator) powerIncreasing := k.getPowerIncreasing(ctx, oldFound, oldValidator, validator) validator.BondHeight, validator.BondIntraTxCounter = k.bondIncrement(ctx, oldFound, oldValidator, validator) - fmt.Printf("Found validator: %v, bond height: %v, counter: %v, old bond height: %v, old counter: %v\n", oldFound, validator.BondHeight, validator.BondIntraTxCounter, oldValidator.BondHeight, oldValidator.BondIntraTxCounter) valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool) cliffPower := k.GetCliffValidatorPower(ctx) @@ -296,10 +295,8 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato // update the list ordered by voting power if oldFound { - fmt.Printf("Delete old key: %X\n", GetValidatorsByPowerIndexKey(oldValidator, pool)) store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool)) } - fmt.Printf("Write new key: %X\n", GetValidatorsByPowerIndexKey(newValidator, pool)) valPower = GetValidatorsByPowerIndexKey(newValidator, pool) store.Set(valPower, newValidator.Owner) @@ -323,8 +320,6 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato func (k Keeper) UpdateBondedValidators(ctx sdk.Context, affectedValidator types.Validator) (updatedVal types.Validator, updated bool) { - fmt.Printf("\nCalling UpdateBondedValidators with %s\n", affectedValidator) - store := ctx.KVStore(k.storeKey) oldCliffValidatorAddr := k.GetCliffValidator(ctx) @@ -333,8 +328,6 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, var validator, validatorToBond types.Validator newValidatorBonded := false - seen := make(map[string]bool) - iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) // largest to smallest for { if !iterator.Valid() || bondedValidatorsCount > int(maxValidators-1) { @@ -346,7 +339,6 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, // validator provided because it has not yet been updated in the store ownerAddr := iterator.Value() if bytes.Equal(ownerAddr, affectedValidator.Owner) { - fmt.Printf("Affected validator: %s\n", affectedValidator) validator = affectedValidator } else { var found bool @@ -369,13 +361,6 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, panic(fmt.Sprintf("revoked validator cannot be bonded, address: %v\n", ownerAddr)) } - fmt.Printf("Iter; on key %X, validator: %s\n", iterator.Key(), validator) - - if seen[string(ownerAddr)] { - panic(fmt.Sprintf("duplicate validator: %s", sdk.AccAddress(ownerAddr))) - } - seen[string(ownerAddr)] = true - iterator.Next() } iterator.Close() @@ -386,10 +371,8 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, // clear or set the cliff validator if bondedValidatorsCount == int(maxValidators) { - fmt.Printf("Setting cliff validator: %s\n", validator) k.setCliffValidator(ctx, validator, k.GetPool(ctx)) } else if len(oldCliffValidatorAddr) > 0 { - fmt.Printf("Clearing cliff validator\n") k.clearCliffValidator(ctx) } @@ -402,8 +385,6 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", oldCliffValidatorAddr)) } - fmt.Printf("Unbonding old cliff validator: %s\n", cliffVal) - fmt.Printf("Then bonding new validator: %s\n", validatorToBond) k.unbondValidator(ctx, cliffVal) } From 14c4642c2ff23c9c8c040335d84d35b0ee001dff Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Sat, 28 Jul 2018 01:06:04 +0200 Subject: [PATCH 25/63] Debugging contd. --- cmd/gaia/app/sim_test.go | 6 +++--- x/stake/handler.go | 4 ++++ x/stake/keeper/validator.go | 13 +++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 2a58c04b6e0a..8b291ebf4ce8 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -117,7 +117,7 @@ func TestFullGaiaSimulation(t *testing.T) { stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgEditValidator(app.stakeKeeper), stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - //stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), @@ -125,8 +125,8 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - // simulation.PeriodicInvariant(allInvariants, 100, 0), - allInvariants, + simulation.PeriodicInvariant(allInvariants, 50, 0), + // allInvariants, }, numKeys, numBlocks, diff --git a/x/stake/handler.go b/x/stake/handler.go index 3cc122e4ca1c..d5cc8f64124f 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -1,6 +1,8 @@ package stake import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/keeper" "github.com/cosmos/cosmos-sdk/x/stake/tags" @@ -104,6 +106,8 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe return ErrNoValidatorFound(k.Codespace()).Result() } + fmt.Printf("HandleMsgEditValidator: %s\n", validator) + // replace all editable fields (clients should autofill existing values) description, err := validator.Description.UpdateDescription(msg.Description) if err != nil { diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 597e665a56e6..349457b2a019 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -209,6 +209,9 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool) cliffPower := k.GetCliffValidatorPower(ctx) + fmt.Printf("valPower: %X\n", valPower) + fmt.Printf("Cliff power: %X\n", cliffPower) + switch { // if already bonded and power increasing only need to update tendermint case powerIncreasing && !validator.Revoked && @@ -295,8 +298,10 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato // update the list ordered by voting power if oldFound { + fmt.Printf("Deleting key: %X\n", GetValidatorsByPowerIndexKey(oldValidator, pool)) store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool)) } + fmt.Printf("Writing key: %X\n", GetValidatorsByPowerIndexKey(newValidator, pool)) valPower = GetValidatorsByPowerIndexKey(newValidator, pool) store.Set(valPower, newValidator.Owner) @@ -320,6 +325,8 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato func (k Keeper) UpdateBondedValidators(ctx sdk.Context, affectedValidator types.Validator) (updatedVal types.Validator, updated bool) { + fmt.Printf("\nCalling UpdateBondedValidators with validator %s\n", affectedValidator) + store := ctx.KVStore(k.storeKey) oldCliffValidatorAddr := k.GetCliffValidator(ctx) @@ -352,6 +359,10 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, if !validator.Revoked { if validator.Status != sdk.Bonded { validatorToBond = validator + fmt.Printf("At count %d of %d, decided to bond: %s\n", bondedValidatorsCount, int(maxValidators-1), validatorToBond) + if newValidatorBonded { + panic("already decided to bond a validator, can't bond another!") + } newValidatorBonded = true } bondedValidatorsCount++ @@ -483,6 +494,8 @@ func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) { // perform all the store operations for when a validator status becomes unbonded func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) types.Validator { + fmt.Printf("Unbonding: %s\n", validator) + store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) From 8ccde07d4f4b2372027342d2c72219e9000b90a5 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Fri, 27 Jul 2018 17:09:40 -0700 Subject: [PATCH 26/63] Merge PR #1842: simulation: Use transition matrices for simulating validator liveness * simulation: Use transition matrices for simulating validator liveness * Make initial distribution follow some weightings --- x/mock/simulation/random_simulate_blocks.go | 54 ++++++++++++---- x/mock/simulation/transition_matrix.go | 70 +++++++++++++++++++++ x/mock/simulation/types.go | 6 ++ x/mock/simulation/util.go | 2 +- 4 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 x/mock/simulation/transition_matrix.go diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e8c80c08bb78..334b3e40f0a9 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -16,6 +16,17 @@ import ( "github.com/stretchr/testify/require" ) +// TODO: Abstract these into parameters later +var ( + // Currently there are 3 different liveness types, fully online, spotty connection, offline. + initialLivenessWeightings = []int{40, 5, 5} + livenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{ + []int{90, 20, 1}, + []int{10, 50, 5}, + []int{0, 10, 1000}, + }) +) + // 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, @@ -46,9 +57,9 @@ func SimulateFromSeed( timeDiff := maxTimePerBlock - minTimePerBlock res := app.InitChain(abci.RequestInitChain{AppStateBytes: appStateFn(r, keys, accs)}) - validators := make(map[string]abci.Validator) + validators := make(map[string]mockValidator) for _, validator := range res.Validators { - validators[string(validator.Address)] = validator + validators[string(validator.Address)] = mockValidator{validator, GetMemberOfInitialState(r, initialLivenessWeightings)} } for i := 0; i < len(setups); i++ { @@ -100,11 +111,11 @@ func SimulateFromSeed( // No BeginBlock simulation request = abci.RequestBeginBlock{} } else { - request = RandomRequestBeginBlock(t, r, validators, signingFraction, evidenceFraction, header.Height, header.Time, log) + request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, header.Height, header.Time, log) } // Update the validator set - validators = UpdateValidators(t, validators, res.ValidatorUpdates) + validators = updateValidators(t, r, validators, res.ValidatorUpdates) } fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) @@ -112,15 +123,26 @@ func SimulateFromSeed( } // 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]abci.Validator, signingFraction float64, evidenceFraction float64, +func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]mockValidator, livenessTransitions TransitionMatrix, evidenceFraction float64, currentHeight int64, currentTime int64, log string) abci.RequestBeginBlock { require.True(t, len(validators) > 0, "Zero validators can't sign a block!") signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 - for _, val := range validators { - signed := r.Float64() < signingFraction + for _, mVal := range validators { + mVal.livenessState = livenessTransitions.NextState(r, mVal.livenessState) + signed := true + + if mVal.livenessState == 1 { + // spotty connection, 50% probability of success + // See https://github.com/golang/go/issues/23804#issuecomment-365370418 + // for reasoning behind computing like this + signed = r.Int63()%2 == 0 + } else if mVal.livenessState == 2 { + // offline + signed = false + } signingValidators[i] = abci.SigningValidator{ - Validator: val, + Validator: mVal.val, SignedLastBlock: signed, } i++ @@ -130,8 +152,8 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]a // TODO Also include past evidence validator := signingValidators[r.Intn(len(signingValidators))].Validator var currentTotalVotingPower int64 - for _, val := range validators { - currentTotalVotingPower += val.Power + for _, mVal := range validators { + currentTotalVotingPower += mVal.val.Power } evidence = append(evidence, abci.Evidence{ Type: "DOUBLE_SIGN", @@ -154,15 +176,21 @@ func AssertAllInvariants(t *testing.T, app *baseapp.BaseApp, tests []Invariant, } } -// UpdateValidators mimicks Tendermint's update logic -func UpdateValidators(t *testing.T, current map[string]abci.Validator, updates []abci.Validator) map[string]abci.Validator { +// updateValidators mimicks Tendermint's update logic +func updateValidators(t *testing.T, r *rand.Rand, current map[string]mockValidator, updates []abci.Validator) 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") delete(current, string(update.PubKey.Data)) default: - current[string(update.PubKey.Data)] = update + // Does validator already exist? + if mVal, ok := current[string(update.PubKey.Data)]; ok { + mVal.val = update + } else { + // Set this new validator + current[string(update.PubKey.Data)] = mockValidator{update, GetMemberOfInitialState(r, initialLivenessWeightings)} + } } } return current diff --git a/x/mock/simulation/transition_matrix.go b/x/mock/simulation/transition_matrix.go new file mode 100644 index 000000000000..39bdb1e4f956 --- /dev/null +++ b/x/mock/simulation/transition_matrix.go @@ -0,0 +1,70 @@ +package simulation + +import ( + "fmt" + "math/rand" +) + +// TransitionMatrix is _almost_ a left stochastic matrix. +// It is technically not one due to not normalizing the column values. +// In the future, if we want to find the steady state distribution, +// it will be quite easy to normalize these values to get a stochastic matrix. +// Floats aren't currently used as the default due to non-determinism across +// architectures +type TransitionMatrix struct { + weights [][]int + // total in each column + totals []int + n int +} + +// CreateTransitionMatrix creates a transition matrix from the provided weights. +// TODO: Provide example usage +func CreateTransitionMatrix(weights [][]int) (TransitionMatrix, error) { + n := len(weights) + for i := 0; i < n; i++ { + if len(weights[i]) != n { + return TransitionMatrix{}, fmt.Errorf("Transition Matrix: Non-square matrix provided, error on row %d", i) + } + } + totals := make([]int, n) + for row := 0; row < n; row++ { + for col := 0; col < n; col++ { + totals[col] += weights[row][col] + } + } + return TransitionMatrix{weights, totals, n}, nil +} + +// NextState returns the next state randomly chosen using r, and the weightings provided +// in the transition matrix. +func (t TransitionMatrix) NextState(r *rand.Rand, i int) int { + randNum := r.Intn(t.totals[i]) + for row := 0; row < t.n; row++ { + if randNum < t.weights[row][i] { + return row + } + randNum -= t.weights[row][i] + } + // This line should never get executed + return -1 +} + +// GetMemberOfInitialState takes an initial array of weights, of size n. +// It returns a weighted random number in [0,n). +func GetMemberOfInitialState(r *rand.Rand, weights []int) int { + n := len(weights) + total := 0 + for i := 0; i < n; i++ { + total += weights[i] + } + randNum := r.Intn(total) + for state := 0; state < n; state++ { + if randNum < weights[state] { + return state + } + randNum -= weights[state] + } + // This line should never get executed + return -1 +} diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 6e1d9f198ffb..35769b0b252d 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" ) @@ -25,6 +26,11 @@ type ( // If the invariant has been broken, the function should halt the // test and output the log. Invariant func(t *testing.T, app *baseapp.BaseApp, log string) + + mockValidator struct { + val abci.Validator + livenessState int + } ) // PeriodicInvariant returns an Invariant function closure that asserts diff --git a/x/mock/simulation/util.go b/x/mock/simulation/util.go index e2983168a417..1d64ba30dd49 100644 --- a/x/mock/simulation/util.go +++ b/x/mock/simulation/util.go @@ -5,7 +5,7 @@ import ( "math/rand" "sort" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto" sdk "github.com/cosmos/cosmos-sdk/types" ) From a2ed2d1554694540b6348d7d7775ebc2f80c2c08 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Sat, 28 Jul 2018 02:17:11 +0200 Subject: [PATCH 27/63] Remove debug Printfs --- x/stake/handler.go | 4 ---- x/stake/keeper/validator.go | 10 ---------- 2 files changed, 14 deletions(-) diff --git a/x/stake/handler.go b/x/stake/handler.go index d5cc8f64124f..3cc122e4ca1c 100644 --- a/x/stake/handler.go +++ b/x/stake/handler.go @@ -1,8 +1,6 @@ package stake import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/stake/keeper" "github.com/cosmos/cosmos-sdk/x/stake/tags" @@ -106,8 +104,6 @@ func handleMsgEditValidator(ctx sdk.Context, msg types.MsgEditValidator, k keepe return ErrNoValidatorFound(k.Codespace()).Result() } - fmt.Printf("HandleMsgEditValidator: %s\n", validator) - // replace all editable fields (clients should autofill existing values) description, err := validator.Description.UpdateDescription(msg.Description) if err != nil { diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 349457b2a019..ebc7a8e259d5 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -209,9 +209,6 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type valPower := k.updateValidatorPower(ctx, oldFound, oldValidator, validator, pool) cliffPower := k.GetCliffValidatorPower(ctx) - fmt.Printf("valPower: %X\n", valPower) - fmt.Printf("Cliff power: %X\n", cliffPower) - switch { // if already bonded and power increasing only need to update tendermint case powerIncreasing && !validator.Revoked && @@ -298,10 +295,8 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato // update the list ordered by voting power if oldFound { - fmt.Printf("Deleting key: %X\n", GetValidatorsByPowerIndexKey(oldValidator, pool)) store.Delete(GetValidatorsByPowerIndexKey(oldValidator, pool)) } - fmt.Printf("Writing key: %X\n", GetValidatorsByPowerIndexKey(newValidator, pool)) valPower = GetValidatorsByPowerIndexKey(newValidator, pool) store.Set(valPower, newValidator.Owner) @@ -325,8 +320,6 @@ func (k Keeper) updateValidatorPower(ctx sdk.Context, oldFound bool, oldValidato func (k Keeper) UpdateBondedValidators(ctx sdk.Context, affectedValidator types.Validator) (updatedVal types.Validator, updated bool) { - fmt.Printf("\nCalling UpdateBondedValidators with validator %s\n", affectedValidator) - store := ctx.KVStore(k.storeKey) oldCliffValidatorAddr := k.GetCliffValidator(ctx) @@ -359,7 +352,6 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, if !validator.Revoked { if validator.Status != sdk.Bonded { validatorToBond = validator - fmt.Printf("At count %d of %d, decided to bond: %s\n", bondedValidatorsCount, int(maxValidators-1), validatorToBond) if newValidatorBonded { panic("already decided to bond a validator, can't bond another!") } @@ -494,8 +486,6 @@ func kickOutValidators(k Keeper, ctx sdk.Context, toKickOut map[string]byte) { // perform all the store operations for when a validator status becomes unbonded func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) types.Validator { - fmt.Printf("Unbonding: %s\n", validator) - store := ctx.KVStore(k.storeKey) pool := k.GetPool(ctx) From 4036295a3951772415c914f7f7a59a466c41e940 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 30 Jul 2018 21:29:45 +0200 Subject: [PATCH 28/63] Governance simulation contd. --- cmd/gaia/app/sim_test.go | 4 ++-- x/gov/keeper.go | 12 ++++++++++++ x/gov/simulation/msgs.go | 39 +++++++++++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 8b291ebf4ce8..0857ffd0af80 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -125,8 +125,8 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - simulation.PeriodicInvariant(allInvariants, 50, 0), - // allInvariants, + // simulation.PeriodicInvariant(allInvariants, 50, 0), + allInvariants, }, numKeys, numBlocks, diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 4f49cac582c6..72cef2d8751b 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -118,6 +118,18 @@ func (keeper Keeper) setInitialProposalID(ctx sdk.Context, proposalID int64) sdk return nil } +// Get the last used proposal ID +func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) { + store := ctx.KVStore(keeper.storeKey) + bz := store.Get(KeyNextProposalID) + if bz == nil { + return 0 + } + keeper.cdc.MustUnmarshalBinary(bz, &proposalID) + proposalID -= 1 + return +} + func (keeper Keeper) getNewProposalID(ctx sdk.Context) (proposalID int64, err sdk.Error) { store := ctx.KVStore(keeper.storeKey) bz := store.Get(KeyNextProposalID) diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 7c81cb0180c2..2dda94c08e6a 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -21,10 +21,11 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd 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()) - deposit := sdk.Coins{sdk.NewCoin("steak", 10)} + // TODO random deposit + deposit := sdk.Coins{sdk.NewCoin("steak", 5)} msg := gov.NewMsgSubmitProposal( - simulation.RandStringOfLength(r, 10), - simulation.RandStringOfLength(r, 10), + simulation.RandStringOfLength(r, 5), + simulation.RandStringOfLength(r, 5), gov.ProposalTypeText, addr, deposit, @@ -32,7 +33,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRat(10)) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRat(5)) sk.SetPool(ctx, pool) result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -50,7 +51,12 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) deposit := sdk.Coins{sdk.NewCoin("steak", 10)} - msg := gov.NewMsgDeposit(addr, int64(1), deposit) + lastProposalID := k.GetLastProposalID(ctx) + if lastProposalID < 1 { + return "no-operation", nil + } + proposalID := int64(r.Intn(int(lastProposalID))) + msg := gov.NewMsgDeposit(addr, proposalID, deposit) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) @@ -71,7 +77,13 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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()) - msg := gov.NewMsgVote(addr, int64(1), gov.OptionYes) + lastProposalID := k.GetLastProposalID(ctx) + if lastProposalID < 1 { + return "no-operation", nil + } + proposalID := int64(r.Intn(int(lastProposalID))) + option := randomVotingOption(r) + msg := gov.NewMsgVote(addr, proposalID, option) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) @@ -83,3 +95,18 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { return action, nil } } + +// Pick a random voting option +func randomVotingOption(r *rand.Rand) gov.VoteOption { + switch r.Intn(4) { + case 0: + return gov.OptionYes + case 1: + return gov.OptionAbstain + case 2: + return gov.OptionNo + case 3: + return gov.OptionNoWithVeto + } + panic("should not happen") +} From 2a9061e5b4044d5e74ddbf84330e4d85cf99d772 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 02:12:28 +0200 Subject: [PATCH 29/63] dep; make format --- Gopkg.lock | 38 ++++++++++----------- docs/sdk/core/examples/app4_test.go | 4 +-- x/bank/app_test.go | 24 ++++++------- x/mock/simulation/random_simulate_blocks.go | 6 ++-- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index e6f15683550e..7ae6cbff2f34 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" + digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" + digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" + digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" + digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,7 +165,7 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -262,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" + digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:32d10bdfa8f09ecf13598324dba86ab891f11db3c538b6a34d1c3b5b99d7c36b" + digest = "1:53a76eb11bdc815fcf0c757a9648fda0ab6887da13f07587181ff2223b67956c" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:e469cd65badf7694aeb44874518606d93c1d59e7735d3754ad442782437d3cc3" + digest = "1:4d291d51042ed9de40eef61a3c1b56e969d6e0f8aa5fd3da5e958ec66bee68e4" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:20d9bb50dbee172242f9bcd6ec24a917dd7a5bb17421bf16a79c33111dea7db1" + digest = "1:55d7449d6987dabf272b4e81b2f9c449f05b17415c939b68d1e82f57e3374b7f" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" + digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" + digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -363,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" + digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:b3cfb8d82b1601a846417c3f31c03a7961862cb2c98dcf0959c473843e6d9a2b" + digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -396,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" + digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -423,7 +423,7 @@ version = "v0.9.2" [[projects]] - digest = "1:e10e95fd9f0a3a31686c9696f8995f6c04b0bc1b4ed0562a4f53cddc0b89d059" + digest = "1:049c779b867a182cea567c65d7c81e3b9e4e4a7eece4c35a19639f75d2aa7da9" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -498,7 +498,7 @@ [[projects]] branch = "master" - digest = "1:65a21a9e051d54eb6a3f70c659a765f706a998d9287c302269f4ed8054b2a852" + digest = "1:e8206c1653e050116ec8c9a823a86413fc9f9ee3c2f3ae977c96d6a1747f7325" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -517,7 +517,7 @@ revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" [[projects]] - digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" + digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" name = "golang.org/x/net" packages = [ "context", @@ -541,7 +541,7 @@ revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" name = "golang.org/x/text" packages = [ "collate", @@ -572,7 +572,7 @@ revision = "e92b116572682a5b432ddd840aeaba2a559eeff1" [[projects]] - digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" + digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" name = "google.golang.org/grpc" packages = [ ".", diff --git a/docs/sdk/core/examples/app4_test.go b/docs/sdk/core/examples/app4_test.go index 2983118431fe..7d95d7b57d8a 100644 --- a/docs/sdk/core/examples/app4_test.go +++ b/docs/sdk/core/examples/app4_test.go @@ -73,7 +73,7 @@ func TestBadMsg(t *testing.T) { if err != nil { panic(err) } - sigs := []auth.StdSignature{auth.StdSignature{ + sigs := []auth.StdSignature{{ PubKey: priv1.PubKey(), Signature: sig, AccountNumber: 0, @@ -119,7 +119,7 @@ func TestMsgSend(t *testing.T) { if err != nil { panic(err) } - sigs := []auth.StdSignature{auth.StdSignature{ + sigs := []auth.StdSignature{{ PubKey: priv1.PubKey(), Signature: sig, AccountNumber: 0, diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 0822a26b7e5a..c8d0a417dc0b 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -113,8 +113,8 @@ func TestMsgSendWithAccounts(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 57)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, + {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 57)}}, + {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, }, }, { @@ -169,9 +169,9 @@ func TestMsgSendMultipleOut(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 47)}}, - expectedBalance{addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}}, + {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, + {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 47)}}, + {addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}}, }, }, } @@ -211,10 +211,10 @@ func TestSengMsgMultipleInOut(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1, priv4}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, - expectedBalance{addr4, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 52)}}, - expectedBalance{addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, + {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, + {addr4, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, + {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 52)}}, + {addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, }, }, } @@ -246,8 +246,8 @@ func TestMsgSendDependent(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv1}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, - expectedBalance{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, + {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}}, + {addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}}, }, }, { @@ -257,7 +257,7 @@ func TestMsgSendDependent(t *testing.T) { expPass: true, privKeys: []crypto.PrivKey{priv2}, expectedBalances: []expectedBalance{ - expectedBalance{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 42)}}, + {addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 42)}}, }, }, } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 334b3e40f0a9..43f55d5efe5a 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -21,9 +21,9 @@ var ( // Currently there are 3 different liveness types, fully online, spotty connection, offline. initialLivenessWeightings = []int{40, 5, 5} livenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{ - []int{90, 20, 1}, - []int{10, 50, 5}, - []int{0, 10, 1000}, + {90, 20, 1}, + {10, 50, 5}, + {0, 10, 1000}, }) ) From 462e0cc35ec1a43588092b74879a4bc0b8329ad0 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 02:17:13 +0200 Subject: [PATCH 30/63] NewInt64Coin --- x/gov/simulation/msgs.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 2dda94c08e6a..8d2b17361903 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -22,7 +22,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd key := simulation.RandomKey(r, keys) addr := sdk.AccAddress(key.PubKey().Address()) // TODO random deposit - deposit := sdk.Coins{sdk.NewCoin("steak", 5)} + deposit := sdk.Coins{sdk.NewInt64Coin("steak", 5)} msg := gov.NewMsgSubmitProposal( simulation.RandStringOfLength(r, 5), simulation.RandStringOfLength(r, 5), @@ -50,7 +50,8 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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()) - deposit := sdk.Coins{sdk.NewCoin("steak", 10)} + // TODO random deposit + deposit := sdk.Coins{sdk.NewInt64Coin("steak", 10)} lastProposalID := k.GetLastProposalID(ctx) if lastProposalID < 1 { return "no-operation", nil From afed98443230a14740c76fac3042b2db9abaeabe Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 03:14:14 +0200 Subject: [PATCH 31/63] Pass header correctly for slashing --- cmd/gaia/app/sim_test.go | 22 ++++++++++----------- x/mock/simulation/random_simulate_blocks.go | 14 +++++++------ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 0857ffd0af80..2b2714374f0e 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -36,8 +36,8 @@ var ( func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") - flag.IntVar(&numKeys, "SimulationNumKeys", 1000, "Number of keys (accounts)") - flag.IntVar(&numBlocks, "SimulationNumBlocks", 1000, "Number of blocks") + flag.IntVar(&numKeys, "SimulationNumKeys", 500, "Number of keys (accounts)") + flag.IntVar(&numBlocks, "SimulationNumBlocks", 500, "Number of blocks") flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 86400, "Minimum time per block (seconds)") flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 2*86400, "Maximum time per block (seconds)") @@ -94,7 +94,7 @@ func TestFullGaiaSimulation(t *testing.T) { } // Setup Gaia application - logger := log.NewNopLogger() + logger := log.TestingLogger() db := dbm.NewMemDB() app := NewGaiaApp(logger, db, nil) require.Equal(t, "GaiaApp", app.Name()) @@ -114,18 +114,18 @@ func TestFullGaiaSimulation(t *testing.T) { govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), - stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgEditValidator(app.stakeKeeper), - stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), - stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), - stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), + //stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), + //stakesim.SimulateMsgEditValidator(app.stakeKeeper), + //stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), + //stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), + //stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), + //stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), + //stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), }, []simulation.RandSetup{}, []simulation.Invariant{ - // simulation.PeriodicInvariant(allInvariants, 50, 0), + //simulation.PeriodicInvariant(allInvariants, 50, 0), allInvariants, }, numKeys, diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 43f55d5efe5a..582ca1862b7d 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -70,7 +70,7 @@ func SimulateFromSeed( header := abci.Header{Height: 0, Time: time} opCount := 0 - request := abci.RequestBeginBlock{} + request := abci.RequestBeginBlock{Header: header} for i := 0; i < numBlocks; i++ { @@ -103,15 +103,16 @@ func SimulateFromSeed( } res := app.EndBlock(abci.RequestEndBlock{}) + app.Commit() header.Height++ header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) // Generate a random RequestBeginBlock with the current validator set for the next block if signingFraction == 0.0 { // No BeginBlock simulation - request = abci.RequestBeginBlock{} + request = abci.RequestBeginBlock{Header: header} } else { - request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, header.Height, header.Time, log) + request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, header, log) } // Update the validator set @@ -124,7 +125,7 @@ func SimulateFromSeed( // 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, - currentHeight int64, currentTime int64, log string) abci.RequestBeginBlock { + header abci.Header, log string) abci.RequestBeginBlock { require.True(t, len(validators) > 0, "Zero validators can't sign a block!") signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 @@ -158,12 +159,13 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m evidence = append(evidence, abci.Evidence{ Type: "DOUBLE_SIGN", Validator: validator, - Height: currentHeight, - Time: currentTime, + Height: header.Height, + Time: header.Time, TotalVotingPower: currentTotalVotingPower, }) } return abci.RequestBeginBlock{ + Header: header, Validators: signingValidators, ByzantineValidators: evidence, } From d69107c90286598d201704c1e20ec5a97281af67 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 03:32:51 +0200 Subject: [PATCH 32/63] Longer timeout; disable inflation --- Makefile | 2 +- cmd/gaia/app/sim_test.go | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 51e4f15f4525..c1bcc764e5b6 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,7 @@ test_sim: @echo "Pass the flag 'SimulationMaxTimePerBlock' to run with the specified maximum block time." @echo "Pass the flag 'SimulationSigningFraction' to run with the specified chance of a given validator signing a given block." @echo "Pass the flag 'SimulationEvidenceFraction' to run with the specified chance of finding evidence on a given block." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -v + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -v -timeout 24h test_cover: @bash tests/test_cover.sh diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 2b2714374f0e..fc524f246394 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -74,6 +74,9 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json stakeGenesis.Pool.LooseTokens = sdk.NewRat(int64(100*numKeys) + (numInitiallyBonded * 100)) stakeGenesis.Validators = validators stakeGenesis.Bonds = delegations + // No inflation, for now + stakeGenesis.Params.InflationMax = sdk.NewRat(0) + stakeGenesis.Params.InflationMin = sdk.NewRat(0) genesis := GenesisState{ Accounts: genesisAccounts, StakeData: stakeGenesis, From c3b9818ded07ba34a2b87d458ddbd7c3c88a1ca7 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 05:40:06 +0200 Subject: [PATCH 33/63] Separate into 'test_sim_modules', 'test_sim_gaia_{fast,slow}' --- .circleci/config.yml | 28 +++++++++++++++++++++++----- Makefile | 28 ++++++++++++++-------------- cmd/gaia/app/sim_test.go | 32 ++++++++++++++++++++------------ 3 files changed, 57 insertions(+), 31 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bf7892a8c26a..20e467f9eb73 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -85,7 +85,7 @@ jobs: export PATH="$GOBIN:$PATH" make test_cli - test_sim: + test_sim_modules: <<: *defaults parallelism: 1 steps: @@ -96,11 +96,26 @@ jobs: - restore_cache: key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} - run: - name: Test simulation + name: Test individual module simulations command: | export PATH="$GOBIN:$PATH" - export GAIA_SIMULATION_SEED=1531897442166404087 - make test_sim + make test_sim_modules + + test_sim_gaia_fast: + <<: *defaults + parallelism: 1 + steps: + - attach_workspace: + at: /tmp/workspace + - restore_cache: + key: v1-pkg-cache + - restore_cache: + key: v1-tree-{{ .Environment.CIRCLE_SHA1 }} + - run: + name: Test full Gaia simulation + command: | + export PATH="$GOBIN:$PATH" + make test_sim_gaia_fast test_cover: <<: *defaults @@ -161,7 +176,10 @@ workflows: - test_cli: requires: - setup_dependencies - - test_sim: + - test_sim_modules: + requires: + - setup_dependencies + - test_sim_gaia_fast: requires: - setup_dependencies - test_cover: diff --git a/Makefile b/Makefile index c1bcc764e5b6..127db897ad4c 100644 --- a/Makefile +++ b/Makefile @@ -130,19 +130,19 @@ test_unit: test_race: @go test -race $(PACKAGES_NOSIMULATION) -test_sim: - @echo "Running individual module simulations." - @go test $(PACKAGES_SIMTEST) -v - @echo "Running full Gaia simulation. This may take several minutes." - @echo "Pass the flag 'SimulationSeed' to run with a constant seed." - @echo "Pass the flag 'SimulationNumKeys' to run with the specified number of keys." - @echo "Pass the flag 'SimulationNumBlocks' to run with the specified number of blocks." - @echo "Pass the flag 'SimulationBlockSize' to run with the specified block size (operations per block)." - @echo "Pass the flag 'SimulationMinTimePerBlock' to run with the specified minimum block time." - @echo "Pass the flag 'SimulationMaxTimePerBlock' to run with the specified maximum block time." - @echo "Pass the flag 'SimulationSigningFraction' to run with the specified chance of a given validator signing a given block." - @echo "Pass the flag 'SimulationEvidenceFraction' to run with the specified chance of finding evidence on a given block." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -v -timeout 24h +test_sim_modules: + @echo "Running individual module simulations..." + @go test $(PACKAGES_SIMTEST) + +test_sim_gaia_fast: + @echo "Running full Gaia simulation. This may take several minutes..." + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=100 -SimulationInvariantInterval=5 \ + -SimulationNumKeys=100 -SimulationBlockSize=50 -timeout 10m + +test_sim_gaia_slow: + @echo "Running full Gaia simulation. This may take several minutes..." + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimuluationNumBlocks=1000 -SimulationInvariantInterval=10 \ + -v -timeout 24h test_cover: @bash tests/test_cover.sh @@ -208,4 +208,4 @@ localnet-stop: check_tools check_dev_tools get_tools get_dev_tools get_vendor_deps draw_deps test test_cli test_unit \ test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update \ build-linux build-docker-gaiadnode localnet-start localnet-stop \ -format check-ledger test_sim update_tools update_dev_tools +format check-ledger test_sim_modules test_sim_gaia_fast test_sim_gaia_slow update_tools update_dev_tools diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index fc524f246394..ccdd8f3f515b 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -23,15 +23,17 @@ import ( ) var ( - seed int64 - numKeys int - numBlocks int - blockSize int - minTimePerBlock int64 - maxTimePerBlock int64 - signingFraction float64 - evidenceFraction float64 - enabled bool + seed int64 + numKeys int + numBlocks int + blockSize int + minTimePerBlock int64 + maxTimePerBlock int64 + signingFraction float64 + evidenceFraction float64 + invariantInterval int + enabled bool + verbose bool ) func init() { @@ -43,7 +45,9 @@ func init() { flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 2*86400, "Maximum time per block (seconds)") flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") flag.Float64Var(&evidenceFraction, "SimulationEvidenceFraction", 0.01, "Chance that any evidence is found on a given block") + flag.IntVar(&invariantInterval, "SimulationInvariantInterval", 10, "Interval between blocks for checking invariants") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") + flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") } func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { @@ -97,7 +101,12 @@ func TestFullGaiaSimulation(t *testing.T) { } // Setup Gaia application - logger := log.TestingLogger() + var logger log.Logger + if verbose { + logger = log.TestingLogger() + } else { + logger = log.NewNopLogger() + } db := dbm.NewMemDB() app := NewGaiaApp(logger, db, nil) require.Equal(t, "GaiaApp", app.Name()) @@ -128,8 +137,7 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - //simulation.PeriodicInvariant(allInvariants, 50, 0), - allInvariants, + simulation.PeriodicInvariant(allInvariants, invariantInterval, 0), }, numKeys, numBlocks, From 23d96f09b82493de8904887361ec3bffe7451787 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 06:02:23 +0200 Subject: [PATCH 34/63] Misc fixes --- Makefile | 8 ++++---- cmd/gaia/app/sim_test.go | 20 ++++++++++++-------- x/bank/simulation/sim_test.go | 2 +- x/gov/keeper.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 10 ++++++---- x/mock/simulation/types.go | 9 +++++---- x/stake/simulation/sim_test.go | 2 +- 7 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 127db897ad4c..4ee890f1ecfa 100644 --- a/Makefile +++ b/Makefile @@ -136,13 +136,13 @@ test_sim_modules: test_sim_gaia_fast: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=100 -SimulationInvariantInterval=5 \ - -SimulationNumKeys=100 -SimulationBlockSize=50 -timeout 10m + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -SimulationInvariantInterval=5 \ + -timeout 10m test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimuluationNumBlocks=1000 -SimulationInvariantInterval=10 \ - -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationInvariantInterval=10 \ + -SimulationVerbose=true -v -timeout 24h test_cover: @bash tests/test_cover.sh diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index ccdd8f3f515b..b431ceed06af 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -32,6 +32,7 @@ var ( signingFraction float64 evidenceFraction float64 invariantInterval int + onOperation bool enabled bool verbose bool ) @@ -46,6 +47,7 @@ func init() { flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") flag.Float64Var(&evidenceFraction, "SimulationEvidenceFraction", 0.01, "Chance that any evidence is found on a given block") flag.IntVar(&invariantInterval, "SimulationInvariantInterval", 10, "Interval between blocks for checking invariants") + flag.BoolVar(&onOperation, "SimulationOnOperation", false, "Check invariants after each operation") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") } @@ -66,6 +68,7 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json stakeGenesis := stake.DefaultGenesisState() var validators []stake.Validator var delegations []stake.Delegation + // XXX Try different numbers of initally bonded validators numInitiallyBonded := int64(50) for i := 0; i < int(numInitiallyBonded); i++ { validator := stake.NewValidator(accs[i], keys[i].PubKey(), stake.Description{}) @@ -126,19 +129,20 @@ func TestFullGaiaSimulation(t *testing.T) { govsim.SimulateMsgSubmitProposal(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgDeposit(app.govKeeper, app.stakeKeeper), govsim.SimulateMsgVote(app.govKeeper, app.stakeKeeper), - //stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), - //stakesim.SimulateMsgEditValidator(app.stakeKeeper), - //stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), - //stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), - //stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), - //stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), - //stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), + stakesim.SimulateMsgCreateValidator(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgEditValidator(app.stakeKeeper), + stakesim.SimulateMsgDelegate(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgBeginUnbonding(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgCompleteUnbonding(app.stakeKeeper), + stakesim.SimulateMsgBeginRedelegate(app.accountMapper, app.stakeKeeper), + stakesim.SimulateMsgCompleteRedelegate(app.stakeKeeper), slashingsim.SimulateMsgUnrevoke(app.slashingKeeper), }, []simulation.RandSetup{}, []simulation.Invariant{ - simulation.PeriodicInvariant(allInvariants, invariantInterval, 0), + simulation.PeriodicInvariant(allInvariants, 10), }, + onOperation, numKeys, numBlocks, blockSize, diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 9e12e57afbfb..252701b4ee8d 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -41,6 +41,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - 100, 30, 30, 10, 20, 0.0, 0.0, + true, 100, 30, 30, 10, 20, 0.0, 0.0, ) } diff --git a/x/gov/keeper.go b/x/gov/keeper.go index 72cef2d8751b..52f88564be7b 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -126,7 +126,7 @@ func (keeper Keeper) GetLastProposalID(ctx sdk.Context) (proposalID int64) { return 0 } keeper.cdc.MustUnmarshalBinary(bz, &proposalID) - proposalID -= 1 + proposalID-- return } diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 582ca1862b7d..05927fe59780 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -30,17 +30,17 @@ var ( // 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, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, + invariants []Invariant, onOperation bool, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock, signingFraction, evidenceFraction) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, onOperation, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock, signingFraction, evidenceFraction) } // 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, - invariants []Invariant, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, + invariants []Invariant, onOperation bool, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) fmt.Printf("%s\n", log) @@ -97,7 +97,9 @@ func SimulateFromSeed( log += "\n" + logUpdate require.Nil(t, err, log) - AssertAllInvariants(t, app, invariants, log) + if onOperation { + AssertAllInvariants(t, app, invariants, log) + } fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) opCount++ } diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 35769b0b252d..542679e9e3f3 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -34,12 +34,13 @@ type ( ) // PeriodicInvariant returns an Invariant function closure that asserts -// a given invariant if the mock application's last block modulo the given -// period is congruent to the given offset. -func PeriodicInvariant(invariant Invariant, period int, offset int) Invariant { +// a given invariant every 1 / period times it is called. +func PeriodicInvariant(invariant Invariant, period int) Invariant { + counter := 0 return func(t *testing.T, app *baseapp.BaseApp, log string) { - if int(app.LastBlockHeight())%period == offset { + if counter == 0 { invariant(t, app, log) } + counter = (counter + 1) % period } } diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 16efef714a1f..9c36384ad831 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -56,6 +56,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, 10, 100, 100, 10, 20, 0.0, 0.0, + }, true, 10, 100, 100, 10, 20, 0.0, 0.0, ) } From fd6594b6f2885c15124c8dcddfc3fade293211fc Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Tue, 31 Jul 2018 06:07:19 +0200 Subject: [PATCH 35/63] Fix teesny-tiny spelling mistake --- cmd/gaia/app/sim_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index b431ceed06af..8ef8c6e4ac9c 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -68,7 +68,7 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json stakeGenesis := stake.DefaultGenesisState() var validators []stake.Validator var delegations []stake.Delegation - // XXX Try different numbers of initally bonded validators + // XXX Try different numbers of initially bonded validators numInitiallyBonded := int64(50) for i := 0; i < int(numInitiallyBonded); i++ { validator := stake.NewValidator(accs[i], keys[i].PubKey(), stake.Description{}) From 416e0d75325da045a9e742ff3e63e36c4b401f83 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 1 Aug 2018 19:53:52 +0200 Subject: [PATCH 36/63] Past evidence; events for BeginBlock/EndBlock --- x/mock/simulation/constants.go | 6 ++++ x/mock/simulation/random_simulate_blocks.go | 32 ++++++++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 x/mock/simulation/constants.go diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go new file mode 100644 index 000000000000..583d043847a8 --- /dev/null +++ b/x/mock/simulation/constants.go @@ -0,0 +1,6 @@ +package simulation + +const ( + // Fraction of double-signing evidence from a past height + pastEvidenceFraction float64 = 0.5 +) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 05927fe59780..e6da1bf913dc 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -72,8 +72,13 @@ func SimulateFromSeed( request := abci.RequestBeginBlock{Header: header} + var pastTimes []int64 + 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) @@ -114,11 +119,11 @@ func SimulateFromSeed( // No BeginBlock simulation request = abci.RequestBeginBlock{Header: header} } else { - request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, header, log) + request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) } // Update the validator set - validators = updateValidators(t, r, validators, res.ValidatorUpdates) + validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) } fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) @@ -127,7 +132,7 @@ func SimulateFromSeed( // 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, - header abci.Header, log string) abci.RequestBeginBlock { + pastTimes []int64, event func(string), header abci.Header, log string) abci.RequestBeginBlock { require.True(t, len(validators) > 0, "Zero validators can't sign a block!") signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 @@ -144,6 +149,11 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m // offline signed = false } + if signed { + event("beginblock/signing/signed") + } else { + event("beginblock/signing/missed") + } signingValidators[i] = abci.SigningValidator{ Validator: mVal.val, SignedLastBlock: signed, @@ -152,7 +162,12 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m } evidence := make([]abci.Evidence, 0) if r.Float64() < evidenceFraction { - // TODO Also include past evidence + height := header.Height + time := header.Time + if r.Float64() < pastEvidenceFraction { + height = int64(r.Intn(int(header.Height))) + time = pastTimes[height] + } validator := signingValidators[r.Intn(len(signingValidators))].Validator var currentTotalVotingPower int64 for _, mVal := range validators { @@ -161,8 +176,8 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m evidence = append(evidence, abci.Evidence{ Type: "DOUBLE_SIGN", Validator: validator, - Height: header.Height, - Time: header.Time, + Height: height, + Time: time, TotalVotingPower: currentTotalVotingPower, }) } @@ -181,19 +196,22 @@ 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) map[string]mockValidator { +func updateValidators(t *testing.T, 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") + event("endblock/validatorupdates/kicked") delete(current, string(update.PubKey.Data)) default: // Does validator already exist? if mVal, ok := current[string(update.PubKey.Data)]; ok { mVal.val = update + event("endblock/validatorupdates/updated") } else { // Set this new validator current[string(update.PubKey.Data)] = mockValidator{update, GetMemberOfInitialState(r, initialLivenessWeightings)} + event("endblock/validatorupdates/added") } } } From 9a4a42baaa0761aa4e4743ad05ea98452b506e81 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 1 Aug 2018 20:04:55 +0200 Subject: [PATCH 37/63] Simplify simulation configuration --- Makefile | 6 ++-- cmd/gaia/app/sim_test.go | 32 ++++----------------- x/bank/simulation/sim_test.go | 2 +- x/mock/simulation/constants.go | 25 ++++++++++++++++ x/mock/simulation/random_simulate_blocks.go | 28 +++++------------- x/stake/simulation/sim_test.go | 2 +- 6 files changed, 42 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index 4ee890f1ecfa..93220ea6d1f1 100644 --- a/Makefile +++ b/Makefile @@ -136,13 +136,11 @@ test_sim_modules: test_sim_gaia_fast: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -SimulationInvariantInterval=5 \ - -timeout 10m + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 10m test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationInvariantInterval=10 \ - -SimulationVerbose=true -v -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h test_cover: @bash tests/test_cover.sh diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 8ef8c6e4ac9c..272d8fd5df22 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -23,31 +23,17 @@ import ( ) var ( - seed int64 - numKeys int - numBlocks int - blockSize int - minTimePerBlock int64 - maxTimePerBlock int64 - signingFraction float64 - evidenceFraction float64 - invariantInterval int - onOperation bool - enabled bool - verbose bool + seed int64 + numBlocks int + blockSize int + enabled bool + verbose bool ) func init() { flag.Int64Var(&seed, "SimulationSeed", 42, "Simulation random seed") - flag.IntVar(&numKeys, "SimulationNumKeys", 500, "Number of keys (accounts)") flag.IntVar(&numBlocks, "SimulationNumBlocks", 500, "Number of blocks") flag.IntVar(&blockSize, "SimulationBlockSize", 200, "Operations per block") - flag.Int64Var(&minTimePerBlock, "SimulationMinTimePerBlock", 86400, "Minimum time per block (seconds)") - flag.Int64Var(&maxTimePerBlock, "SimulationMaxTimePerBlock", 2*86400, "Maximum time per block (seconds)") - flag.Float64Var(&signingFraction, "SimulationSigningFraction", 0.7, "Chance a given validator signs a given block") - flag.Float64Var(&evidenceFraction, "SimulationEvidenceFraction", 0.01, "Chance that any evidence is found on a given block") - flag.IntVar(&invariantInterval, "SimulationInvariantInterval", 10, "Interval between blocks for checking invariants") - flag.BoolVar(&onOperation, "SimulationOnOperation", false, "Check invariants after each operation") flag.BoolVar(&enabled, "SimulationEnabled", false, "Enable the simulation") flag.BoolVar(&verbose, "SimulationVerbose", false, "Verbose log output") } @@ -78,7 +64,7 @@ func appStateFn(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json validators = append(validators, validator) delegations = append(delegations, delegation) } - stakeGenesis.Pool.LooseTokens = sdk.NewRat(int64(100*numKeys) + (numInitiallyBonded * 100)) + stakeGenesis.Pool.LooseTokens = sdk.NewRat(int64(100*250) + (numInitiallyBonded * 100)) stakeGenesis.Validators = validators stakeGenesis.Bonds = delegations // No inflation, for now @@ -142,14 +128,8 @@ func TestFullGaiaSimulation(t *testing.T) { []simulation.Invariant{ simulation.PeriodicInvariant(allInvariants, 10), }, - onOperation, - numKeys, numBlocks, blockSize, - minTimePerBlock, - maxTimePerBlock, - signingFraction, - evidenceFraction, ) } diff --git a/x/bank/simulation/sim_test.go b/x/bank/simulation/sim_test.go index 252701b4ee8d..49e3dfa92f2d 100644 --- a/x/bank/simulation/sim_test.go +++ b/x/bank/simulation/sim_test.go @@ -41,6 +41,6 @@ func TestBankWithRandomMessages(t *testing.T) { NonnegativeBalanceInvariant(mapper), TotalCoinsInvariant(mapper, func() sdk.Coins { return mapp.TotalCoinsSupply }), }, - true, 100, 30, 30, 10, 20, 0.0, 0.0, + 30, 30, ) } diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index 583d043847a8..5c5723e6cb9b 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -3,4 +3,29 @@ package simulation const ( // Fraction of double-signing evidence from a past height pastEvidenceFraction float64 = 0.5 + + // Minimum time per block + minTimePerBlock int64 = 86400 / 2 + + // Maximum time per block + maxTimePerBlock int64 = 86400 + + // Number of keys + numKeys int = 250 + + // Chance that double-signing evidence is found on a given block + evidenceFraction float64 = 0.01 + + // TODO Remove in favor of search + onOperation bool = false +) + +var ( + // Currently there are 3 different liveness types, fully online, spotty connection, offline. + initialLivenessWeightings = []int{40, 5, 5} + livenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{ + {90, 20, 1}, + {10, 50, 5}, + {0, 10, 1000}, + }) ) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e6da1bf913dc..967523090be2 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -16,31 +16,20 @@ import ( "github.com/stretchr/testify/require" ) -// TODO: Abstract these into parameters later -var ( - // Currently there are 3 different liveness types, fully online, spotty connection, offline. - initialLivenessWeightings = []int{40, 5, 5} - livenessTransitionMatrix, _ = CreateTransitionMatrix([][]int{ - {90, 20, 1}, - {10, 50, 5}, - {0, 10, 1000}, - }) -) - // 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, - invariants []Invariant, onOperation bool, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, + invariants []Invariant, numBlocks int, blockSize int, ) { time := time.Now().UnixNano() - SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, onOperation, numKeys, numBlocks, blockSize, minTimePerBlock, maxTimePerBlock, signingFraction, evidenceFraction) + SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize) } // 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, - invariants []Invariant, onOperation bool, numKeys int, numBlocks int, blockSize int, minTimePerBlock int64, maxTimePerBlock int64, signingFraction float64, evidenceFraction float64, + invariants []Invariant, numBlocks int, blockSize int, ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) fmt.Printf("%s\n", log) @@ -115,12 +104,7 @@ func SimulateFromSeed( header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) // Generate a random RequestBeginBlock with the current validator set for the next block - if signingFraction == 0.0 { - // No BeginBlock simulation - request = abci.RequestBeginBlock{Header: header} - } else { - request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) - } + request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) // Update the validator set validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) @@ -133,7 +117,9 @@ func SimulateFromSeed( // 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 []int64, event func(string), header abci.Header, log string) abci.RequestBeginBlock { - require.True(t, len(validators) > 0, "Zero validators can't sign a block!") + if len(validators) == 0 { + return abci.RequestBeginBlock{Header: header} + } signingValidators := make([]abci.SigningValidator, len(validators)) i := 0 for _, mVal := range validators { diff --git a/x/stake/simulation/sim_test.go b/x/stake/simulation/sim_test.go index 9c36384ad831..3e80e1eb3f3e 100644 --- a/x/stake/simulation/sim_test.go +++ b/x/stake/simulation/sim_test.go @@ -56,6 +56,6 @@ func TestStakeWithRandomMessages(t *testing.T) { Setup(mapp, stakeKeeper), }, []simulation.Invariant{ AllInvariants(coinKeeper, stakeKeeper, mapp.AccountMapper), - }, true, 10, 100, 100, 10, 20, 0.0, 0.0, + }, 10, 100, ) } From dfb81f00c63931db91e4a033fdf1ffaa41506884 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 1 Aug 2018 20:16:05 +0200 Subject: [PATCH 38/63] Add module simulation for x/gov --- x/gov/simulation/sim_test.go | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 x/gov/simulation/sim_test.go diff --git a/x/gov/simulation/sim_test.go b/x/gov/simulation/sim_test.go new file mode 100644 index 000000000000..e7131f8fcc75 --- /dev/null +++ b/x/gov/simulation/sim_test.go @@ -0,0 +1,68 @@ +package simulation + +import ( + "encoding/json" + "math/rand" + "testing" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/gov" + "github.com/cosmos/cosmos-sdk/x/mock" + "github.com/cosmos/cosmos-sdk/x/mock/simulation" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/stake" +) + +// TestGovWithRandomMessages +func TestGovWithRandomMessages(t *testing.T) { + mapp := mock.NewApp() + + bank.RegisterWire(mapp.Cdc) + gov.RegisterWire(mapp.Cdc) + mapper := mapp.AccountMapper + coinKeeper := bank.NewKeeper(mapper) + stakeKey := sdk.NewKVStoreKey("stake") + stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, coinKeeper, stake.DefaultCodespace) + paramKey := sdk.NewKVStoreKey("params") + paramKeeper := params.NewKeeper(mapp.Cdc, paramKey) + govKey := sdk.NewKVStoreKey("gov") + govKeeper := gov.NewKeeper(mapp.Cdc, govKey, paramKeeper.Setter(), coinKeeper, stakeKeeper, gov.DefaultCodespace) + mapp.Router().AddRoute("gov", gov.NewHandler(govKeeper)) + mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + gov.EndBlocker(ctx, govKeeper) + return abci.ResponseEndBlock{} + }) + + err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey, paramKey, govKey}) + if err != nil { + panic(err) + } + + appStateFn := func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage { + mock.RandomSetGenesis(r, mapp, accs, []string{"stake"}) + return json.RawMessage("{}") + } + + setup := func(r *rand.Rand, privKeys []crypto.PrivKey) { + ctx := mapp.NewContext(false, abci.Header{}) + stake.InitGenesis(ctx, stakeKeeper, stake.DefaultGenesisState()) + gov.InitGenesis(ctx, govKeeper, gov.DefaultGenesisState()) + } + + simulation.Simulate( + t, mapp.BaseApp, appStateFn, + []simulation.TestAndRunTx{ + SimulateMsgSubmitProposal(govKeeper, stakeKeeper), + SimulateMsgDeposit(govKeeper, stakeKeeper), + SimulateMsgVote(govKeeper, stakeKeeper), + }, []simulation.RandSetup{ + setup, + }, []simulation.Invariant{ + AllInvariants(), + }, 10, 100, + ) +} From ebd394c2593e673d5bcb2daf911d7b43758136ac Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 18:46:39 +0200 Subject: [PATCH 39/63] Fix BeginBlock on existing deliverState.ctx --- baseapp/baseapp.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 03a374bcd522..030051eb89ed 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -379,7 +379,7 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg } else { // In the first block, app.deliverState.ctx will already be initialized // by InitChain. Context is now updated with Header information. - app.deliverState.ctx = app.deliverState.ctx.WithBlockHeader(req.Header) + app.deliverState.ctx = app.deliverState.ctx.WithBlockHeader(req.Header).WithBlockHeight(req.Header.Height) } if app.beginBlocker != nil { diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 967523090be2..e083e22a5634 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -54,7 +54,6 @@ func SimulateFromSeed( for i := 0; i < len(setups); i++ { setups[i](r, keys) } - app.Commit() header := abci.Header{Height: 0, Time: time} opCount := 0 @@ -99,7 +98,6 @@ func SimulateFromSeed( } res := app.EndBlock(abci.RequestEndBlock{}) - app.Commit() header.Height++ header.Time += minTimePerBlock + int64(r.Intn(int(timeDiff))) From 03d9378fbca6ce488c08d3a99dbe7ad33d30e6f5 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 18:52:09 +0200 Subject: [PATCH 40/63] Minor cleanup --- cmd/gaia/app/sim_test.go | 2 +- x/mock/simulation/constants.go | 2 +- x/mock/simulation/types.go | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 272d8fd5df22..18d3c809e825 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -126,7 +126,7 @@ func TestFullGaiaSimulation(t *testing.T) { }, []simulation.RandSetup{}, []simulation.Invariant{ - simulation.PeriodicInvariant(allInvariants, 10), + allInvariants, }, numBlocks, blockSize, diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index 5c5723e6cb9b..985a22dcac72 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -16,7 +16,7 @@ const ( // Chance that double-signing evidence is found on a given block evidenceFraction float64 = 0.01 - // TODO Remove in favor of search + // TODO Remove in favor of binary search for invariant violation onOperation bool = false ) diff --git a/x/mock/simulation/types.go b/x/mock/simulation/types.go index 542679e9e3f3..35769b0b252d 100644 --- a/x/mock/simulation/types.go +++ b/x/mock/simulation/types.go @@ -34,13 +34,12 @@ type ( ) // PeriodicInvariant returns an Invariant function closure that asserts -// a given invariant every 1 / period times it is called. -func PeriodicInvariant(invariant Invariant, period int) Invariant { - counter := 0 +// a given invariant if the mock application's last block modulo the given +// period is congruent to the given offset. +func PeriodicInvariant(invariant Invariant, period int, offset int) Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { - if counter == 0 { + if int(app.LastBlockHeight())%period == offset { invariant(t, app, log) } - counter = (counter + 1) % period } } From 36aa0af9a4f3ed5b7ab6fb2ce412ab25d440d217 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 19:01:14 +0200 Subject: [PATCH 41/63] Cleanup x/gov simulation msgs --- x/gov/simulation/msgs.go | 41 ++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index 8d2b17361903..f35906dc86ed 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -16,13 +16,16 @@ import ( "github.com/cosmos/cosmos-sdk/x/stake" ) +const ( + denom = "steak" +) + // SimulateMsgSubmitProposal func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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()) - // TODO random deposit - deposit := sdk.Coins{sdk.NewInt64Coin("steak", 5)} + deposit := randomDeposit(r) msg := gov.NewMsgSubmitProposal( simulation.RandStringOfLength(r, 5), simulation.RandStringOfLength(r, 5), @@ -33,7 +36,7 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRat(5)) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) sk.SetPool(ctx, pool) result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { @@ -50,19 +53,17 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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()) - // TODO random deposit - deposit := sdk.Coins{sdk.NewInt64Coin("steak", 10)} - lastProposalID := k.GetLastProposalID(ctx) - if lastProposalID < 1 { + proposalID, ok := randomProposalID(r, k, ctx) + if !ok { return "no-operation", nil } - proposalID := int64(r.Intn(int(lastProposalID))) + deposit := randomDeposit(r) msg := gov.NewMsgDeposit(addr, proposalID, deposit) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRat(10)) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) sk.SetPool(ctx, pool) if result.IsOK() { write() @@ -78,11 +79,10 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { 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()) - lastProposalID := k.GetLastProposalID(ctx) - if lastProposalID < 1 { + proposalID, ok := randomProposalID(r, k, ctx) + if !ok { return "no-operation", nil } - proposalID := int64(r.Intn(int(lastProposalID))) option := randomVotingOption(r) msg := gov.NewMsgVote(addr, proposalID, option) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) @@ -97,6 +97,23 @@ func SimulateMsgVote(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { } } +// Pick a random deposit +func randomDeposit(r *rand.Rand) sdk.Coins { + // TODO Choose based on account balance and min deposit + amount := int64(r.Intn(20)) + 1 + return sdk.Coins{sdk.NewInt64Coin(denom, amount)} +} + +// Pick a random proposal ID +func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID int64, ok bool) { + lastProposalID := k.GetLastProposalID(ctx) + if lastProposalID < 1 { + return 0, false + } + proposalID = int64(r.Intn(int(lastProposalID))) + return proposalID, true +} + // Pick a random voting option func randomVotingOption(r *rand.Rand) gov.VoteOption { switch r.Intn(4) { From d9c1d67b52c7cc4bf1e70e45455bbe1dee7f1013 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 19:10:40 +0200 Subject: [PATCH 42/63] Log proposal EndBlocker events --- x/gov/handler.go | 11 +++++++++++ x/gov/simulation/invariants.go | 2 ++ 2 files changed, 13 insertions(+) diff --git a/x/gov/handler.go b/x/gov/handler.go index 747671cbac6c..90640314815f 100644 --- a/x/gov/handler.go +++ b/x/gov/handler.go @@ -96,6 +96,8 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result { // Called every block, process inflation, update validator set func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { + logger := ctx.Logger().With("module", "x/gov") + resTags = sdk.NewTags() // Delete proposals that haven't met minDeposit @@ -109,6 +111,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { keeper.DeleteProposal(ctx, inactiveProposal) resTags.AppendTag(tags.Action, tags.ActionProposalDropped) resTags.AppendTag(tags.ProposalID, proposalIDBytes) + + logger.Info("Proposal %d - \"%s\" - didn't mean minimum deposit (had only %s), deleted", + inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), inactiveProposal.GetTotalDeposit()) } var passes bool @@ -138,6 +143,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { } keeper.SetProposal(ctx, activeProposal) + logger.Info("Proposal %d - \"%s\" - tallied, passed: %v", + activeProposal.GetProposalID(), activeProposal.GetTitle(), passes) + for _, valAddr := range nonVotingVals { val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr) keeper.ds.GetValidatorSet().Slash(ctx, @@ -145,6 +153,9 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) { ctx.BlockHeight(), val.GetPower().RoundInt64(), keeper.GetTallyingProcedure(ctx).GovernancePenalty) + + logger.Info("Validator %s failed to vote on proposal %d, slashing", + val.GetOwner(), activeProposal.GetProposalID()) } resTags.AppendTag(tags.Action, action) diff --git a/x/gov/simulation/invariants.go b/x/gov/simulation/invariants.go index a958de26a00e..e9275f3c1a8b 100644 --- a/x/gov/simulation/invariants.go +++ b/x/gov/simulation/invariants.go @@ -12,6 +12,8 @@ import ( // AllInvariants tests all governance invariants func AllInvariants() simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { + // TODO Add some invariants! + // Checking proposal queues, no passed-but-unexecuted proposals, etc. require.Nil(t, nil) } } From fadfe879390bc6a01c0b126d9155590a6bd096df Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 19:16:45 +0200 Subject: [PATCH 43/63] Update PENDING.md --- PENDING.md | 5 +++++ x/slashing/simulation/invariants.go | 1 + 2 files changed, 6 insertions(+) diff --git a/PENDING.md b/PENDING.md index f13f3021e8fe..149bdc16126d 100644 --- a/PENDING.md +++ b/PENDING.md @@ -35,6 +35,9 @@ FEATURES * Modules specify invariants and operations, preferably in an x/[module]/simulation package * Modules can test random combinations of their own operations * Applications can integrate operations and invariants from modules together for an integrated simulation + * Simulates Tendermint's algorithm for validator set updates + * Simulates validator signing/downtime with a Markov chain, and occaisional double-signatures + * Includes simulated operations & invariants for staking, slashing, governance, and bank modules * [baseapp] Initialize validator set on ResponseInitChain * [cosmos-sdk-cli] Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd * This allows SDK users to initialize a new project repository. @@ -58,6 +61,7 @@ IMPROVEMENTS * [tests] \#1806 CLI tests are now behind the build flag 'cli_test', so go test works on a new repo * [x/gov] Initial governance parameters can now be set in the genesis file * [x/stake] \#1815 Sped up the processing of `EditValidator` txs. +* [x/gov] Added simple logging for proposal expiry & tally events using ctx.Logger BUG FIXES * \#1666 Add intra-tx counter to the genesis validators @@ -69,3 +73,4 @@ BUG FIXES * \#1828 Force user to specify amount on create-validator command by removing default * \#1839 Fixed bug where intra-tx counter wasn't set correctly for genesis validators * [tests] \#1675 Fix non-deterministic `test_cover` +* [baseapp] ctx.BlockHeight now correctly set on BeginBlock when app.deliverState is non-nil diff --git a/x/slashing/simulation/invariants.go b/x/slashing/simulation/invariants.go index f2c65d9e3da3..7352aa503228 100644 --- a/x/slashing/simulation/invariants.go +++ b/x/slashing/simulation/invariants.go @@ -12,6 +12,7 @@ import ( // AllInvariants tests all slashing invariants func AllInvariants() simulation.Invariant { return func(t *testing.T, app *baseapp.BaseApp, log string) { + // TODO Any invariants to check here? require.Nil(t, nil) } } From 7b2b9893ed7c993881ffb18064d07abb3be23020 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 19:18:33 +0200 Subject: [PATCH 44/63] Minor fixes --- PENDING.md | 1 + x/stake/keeper/validator.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PENDING.md b/PENDING.md index 149bdc16126d..c69567392d10 100644 --- a/PENDING.md +++ b/PENDING.md @@ -62,6 +62,7 @@ IMPROVEMENTS * [x/gov] Initial governance parameters can now be set in the genesis file * [x/stake] \#1815 Sped up the processing of `EditValidator` txs. * [x/gov] Added simple logging for proposal expiry & tally events using ctx.Logger +* [x/stake] Added several sanity checks in UpdateValidator() BUG FIXES * \#1666 Add intra-tx counter to the genesis validators diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 0306c2886de7..6058f8ebdb2a 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -491,7 +491,7 @@ func (k Keeper) unbondValidator(ctx sdk.Context, validator types.Validator) type // sanity check if validator.Status == sdk.Unbonded { - panic(fmt.Sprintf("should not already be unbonded, validator: %s\n", validator)) + panic(fmt.Sprintf("should not already be unbonded, validator: %v\n", validator)) } // set the status @@ -518,7 +518,7 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types. // sanity check if validator.Status == sdk.Bonded { - panic(fmt.Sprintf("should not already be bonded, validator: %s\n", validator)) + panic(fmt.Sprintf("should not already be bonded, validator: %v\n", validator)) } // set the status From 73d50288cbef6b0335cefc2b62248b4c6f227113 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 3 Aug 2018 19:33:49 +0200 Subject: [PATCH 45/63] Correct evidence type --- Gopkg.lock | 31 +++++++++++---------- x/mock/simulation/random_simulate_blocks.go | 3 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 7ae6cbff2f34..0cc573d8b91c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -38,7 +38,7 @@ name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "fdfc19097e7ac6b57035062056f5b7b4638b8898" + revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -165,12 +165,13 @@ [[projects]] branch = "master" - digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f" + digest = "1:ac64f01acc5eeea9dde40e326de6b6471e501392ec06524c3b51033aa50789bc" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -231,11 +232,11 @@ [[projects]] branch = "master" - digest = "1:e730597b38a4d56e2361e0b6236cb800e52c73cace2ff91396f4ff35792ddfa7" + digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" name = "github.com/mitchellh/mapstructure" packages = ["."] pruneopts = "UT" - revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" + revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" [[projects]] digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e" @@ -273,15 +274,15 @@ [[projects]] branch = "master" - digest = "1:53a76eb11bdc815fcf0c757a9648fda0ab6887da13f07587181ff2223b67956c" + digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" - revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" [[projects]] branch = "master" - digest = "1:4d291d51042ed9de40eef61a3c1b56e969d6e0f8aa5fd3da5e958ec66bee68e4" + digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -289,11 +290,11 @@ "model", ] pruneopts = "UT" - revision = "7600349dcfe1abd18d72d3a1770870d9800a7801" + revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" [[projects]] branch = "master" - digest = "1:55d7449d6987dabf272b4e81b2f9c449f05b17415c939b68d1e82f57e3374b7f" + digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" name = "github.com/prometheus/procfs" packages = [ ".", @@ -302,7 +303,7 @@ "xfs", ] pruneopts = "UT" - revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a" + revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" [[projects]] digest = "1:c4556a44e350b50a490544d9b06e9fba9c286c21d6c0e47f54f3a9214597298c" @@ -514,7 +515,7 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" + revision = "56440b844dfe139a8ac053f4ecac0b20b79058f4" [[projects]] digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" @@ -534,11 +535,11 @@ [[projects]] branch = "master" - digest = "1:d773e525476aefa22ea944a5425a9bfb99819b2e67eeb9b1966454fd57522bbf" + digest = "1:9ec6ad2659635ba0974dd7e55bf84233523eb4e7535c9a2fddaefc4cc62a3eac" name = "golang.org/x/sys" packages = ["unix"] pruneopts = "UT" - revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2" + revision = "0ffbfd41fbef8ffcf9b62b0b0aa3a5873ed7a4fe" [[projects]] digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" @@ -565,11 +566,11 @@ [[projects]] branch = "master" - digest = "1:601e63e7d4577f907118bec825902505291918859d223bce015539e79f1160e3" + digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "e92b116572682a5b432ddd840aeaba2a559eeff1" + revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" [[projects]] digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index e083e22a5634..dacf459b0b91 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -9,6 +9,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" + tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -158,7 +159,7 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m currentTotalVotingPower += mVal.val.Power } evidence = append(evidence, abci.Evidence{ - Type: "DOUBLE_SIGN", + Type: tmtypes.ABCIEvidenceTypeDuplicateVote, Validator: validator, Height: height, Time: time, From bce3f5d3b673a155c99448685ac60390fc3c75ed Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 9 Aug 2018 16:28:40 -0500 Subject: [PATCH 46/63] reduce unnecessarsy verbosity --- x/mock/simulation/random_simulate_blocks.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index dacf459b0b91..56043ba88ce5 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -94,7 +94,9 @@ func SimulateFromSeed( if onOperation { AssertAllInvariants(t, app, invariants, log) } - fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) + if opCount%200 == 0 { + fmt.Printf("\rSimulating... block %d/%d, operation %d.", header.Height, numBlocks, opCount) + } opCount++ } From 268c0ac0d6bc0ae756f17d51a4f3d0e599661c67 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 10 Aug 2018 15:59:01 +0200 Subject: [PATCH 47/63] dep ensure -v -update --- Gopkg.lock | 55 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index c69af1c2e1bf..ef37ffa23781 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,11 +34,11 @@ [[projects]] branch = "master" - digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" + digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" - revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8" + revision = "f899737d7f2764dc13e4d01ff00108ec58f766a9" [[projects]] digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" + digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" + digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" + digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,13 +165,12 @@ [[projects]] branch = "master" - digest = "1:ac64f01acc5eeea9dde40e326de6b6471e501392ec06524c3b51033aa50789bc" + digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", - "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -263,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" + digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -274,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" + digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -282,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" + digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -294,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" + digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", @@ -313,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", @@ -332,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -348,12 +347,12 @@ revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" [[projects]] - digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" + digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" name = "github.com/spf13/pflag" packages = ["."] pruneopts = "UT" - revision = "583c0c0531f06d5278b7d917446061adc344b5cd" - version = "v1.0.1" + revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" + version = "v1.0.2" [[projects]] digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96" @@ -364,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" + digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", @@ -376,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" + digest = "1:b3cfb8d82b1601a846417c3f31c03a7961862cb2c98dcf0959c473843e6d9a2b" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -397,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" + digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -424,7 +423,7 @@ version = "v0.9.2" [[projects]] - digest = "1:049c779b867a182cea567c65d7c81e3b9e4e4a7eece4c35a19639f75d2aa7da9" + digest = "1:e10e95fd9f0a3a31686c9696f8995f6c04b0bc1b4ed0562a4f53cddc0b89d059" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -499,7 +498,7 @@ [[projects]] branch = "master" - digest = "1:e8206c1653e050116ec8c9a823a86413fc9f9ee3c2f3ae977c96d6a1747f7325" + digest = "1:65a21a9e051d54eb6a3f70c659a765f706a998d9287c302269f4ed8054b2a852" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -515,10 +514,10 @@ "salsa20/salsa", ] pruneopts = "UT" - revision = "f027049dab0ad238e394a753dba2d14753473a04" + revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] - digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" + digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -535,14 +534,14 @@ [[projects]] branch = "master" - digest = "1:4d7a8265af700258feaff86722049eb5b787240d66dfaf45ff4962f09de6e0be" + digest = "1:2bcc8ab17d0dfedd170ce2a8caaeea47b8302489bb94bd4bd819f90cf3a5288e" name = "golang.org/x/sys" packages = ["unix"] pruneopts = "UT" - revision = "acbc56fc7007d2a01796d5bde54f39e3b3e95945" + revision = "f0d5e33068cb57c22a181f5df0ffda885309eb5a" [[projects]] - digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -570,10 +569,10 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "daca94659cb50e9f37c1b834680f2e46358f10b0" + revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] - digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", From f18c01d2919d867b631a6d868c5fa725606fc437 Mon Sep 17 00:00:00 2001 From: Zach Date: Mon, 13 Aug 2018 07:15:01 -0400 Subject: [PATCH 48/63] Merge PR #1994: Delete install.md --- docs/install.md | 59 ------------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 docs/install.md diff --git a/docs/install.md b/docs/install.md deleted file mode 100644 index bafdfc4bdeb9..000000000000 --- a/docs/install.md +++ /dev/null @@ -1,59 +0,0 @@ -# Install - -The fastest and easiest way to install the Cosmos SDK binaries -is to run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_ubuntu.sh) on a fresh Ubuntu instance. Similarly, you can run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_bsd.sh) on a fresh FreeBSD instance. Read the scripts before running them to ensure no untrusted connection is being made, for example we're making curl requests to download golang. Also read the comments / instructions carefully (i.e., reset your terminal after running the script). - -Cosmos SDK can be installed to -`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program: - -``` -go get github.com/cosmos/cosmos-sdk -``` - -If the dependencies have been updated with breaking changes, or if -another branch is required, `dep` is used for dependency management. -Thus, assuming you've already run `go get` or otherwise cloned the repo, -the correct way to install is: - -``` -cd $GOPATH/src/github.com/cosmos/cosmos-sdk -make get_tools -make get_vendor_deps -make install -make install_examples -``` - -This will install `gaiad` and `gaiacli` and four example binaries: -`basecoind`, `basecli`, `democoind`, and `democli`. - -Verify that everything is OK by running: - -``` -gaiad version -``` - -you should see: - -``` -0.17.3-a5a78eb -``` - -then with: - -``` -gaiacli version -``` -you should see the same version (or a later one for both). - -## Update - -Get latest code (you can also `git fetch` only the version desired), -ensure the dependencies are up to date, then recompile. - -``` -cd $GOPATH/src/github.com/cosmos/cosmos-sdk -git fetch -a origin -git checkout VERSION -make get_vendor_deps -make install -``` From 1a64c8747cbe1d0717aa93dabe393997f99e2027 Mon Sep 17 00:00:00 2001 From: Juan Leni Date: Mon, 13 Aug 2018 13:21:05 +0200 Subject: [PATCH 49/63] Merge PR #1995: upgrading ledger goclient lib --- Gopkg.lock | 4 ++-- Gopkg.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 8fcb2fb5e5b5..3383e66598a9 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -490,11 +490,11 @@ version = "v0.23.0" [[projects]] - digest = "1:5bd938386bd1f61a581bf8cd6ff2b7b2f79c542929176db4ceb44965440dae07" + digest = "1:2ea7665579c64cda1873a395de97a2af02df1d06f4cb52128caf57f13249303c" name = "github.com/zondax/ledger-goclient" packages = ["."] pruneopts = "UT" - revision = "39ba4728c137c75718a21f9b4b3280fa31b9139b" + revision = "a05312e1c998ad831b70eea41d009654f7f95985" [[projects]] branch = "master" diff --git a/Gopkg.toml b/Gopkg.toml index 1c7019ae6e6a..63356c240c50 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -65,7 +65,7 @@ [[constraint]] name = "github.com/zondax/ledger-goclient" - revision = "39ba4728c137c75718a21f9b4b3280fa31b9139b" + revision = "a05312e1c998ad831b70eea41d009654f7f95985" [prune] go-tests = true From b40c9e818d22f7b79db7281cdffca666335002db Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 13 Aug 2018 14:14:07 +0200 Subject: [PATCH 50/63] Remove simulation from 'make test_cover' --- tests/test_cover.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cover.sh b/tests/test_cover.sh index be6215b5a1b6..3fb0ab69cac3 100644 --- a/tests/test_cover.sh +++ b/tests/test_cover.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -PKGS=$(go list ./... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test) +PKGS=$(go list ./... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | grep -v '/simulation') set -e echo "mode: atomic" > coverage.txt From 198f0f32442d23a74d34ca54145bd5a81510a217 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 13 Aug 2018 14:21:59 +0200 Subject: [PATCH 51/63] .ABCIValidator() includes address --- types/stake.go | 5 +++-- x/stake/types/validator.go | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/types/stake.go b/types/stake.go index 4e3cf38a3233..f611a2b5162a 100644 --- a/types/stake.go +++ b/types/stake.go @@ -51,8 +51,9 @@ type Validator interface { // validator which fulfills abci validator interface for use in Tendermint func ABCIValidator(v Validator) abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.GetPubKey()), - Power: v.GetPower().RoundInt64(), + PubKey: tmtypes.TM2PB.PubKey(v.GetPubKey()), + Address: v.GetPubKey().Address(), + Power: v.GetPower().RoundInt64(), } } diff --git a/x/stake/types/validator.go b/x/stake/types/validator.go index 837b8f8e8a02..089e8ea92ad8 100644 --- a/x/stake/types/validator.go +++ b/x/stake/types/validator.go @@ -314,8 +314,9 @@ func (d Description) EnsureLength() (Description, sdk.Error) { // ABCIValidator returns an abci.Validator from a staked validator type. func (v Validator) ABCIValidator() abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.PubKey), - Power: v.BondedTokens().RoundInt64(), + PubKey: tmtypes.TM2PB.PubKey(v.PubKey), + Address: v.PubKey.Address(), + Power: v.BondedTokens().RoundInt64(), } } @@ -323,8 +324,9 @@ func (v Validator) ABCIValidator() abci.Validator { // with with zero power used for validator updates. func (v Validator) ABCIValidatorZero() abci.Validator { return abci.Validator{ - PubKey: tmtypes.TM2PB.PubKey(v.PubKey), - Power: 0, + PubKey: tmtypes.TM2PB.PubKey(v.PubKey), + Address: v.PubKey.Address(), + Power: 0, } } From f172dd678a8d00894a84ededabb70365ec926d63 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 13 Aug 2018 14:25:16 +0200 Subject: [PATCH 52/63] Minor fixes --- Makefile | 2 +- x/gov/simulation/msgs.go | 14 ++++++++------ x/mock/simulation/constants.go | 2 +- x/mock/simulation/random_simulate_blocks.go | 8 ++++++++ 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 93220ea6d1f1..825b0b4ce01e 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ test_sim_modules: test_sim_gaia_fast: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 10m + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 2h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take several minutes..." diff --git a/x/gov/simulation/msgs.go b/x/gov/simulation/msgs.go index f35906dc86ed..596a013d3452 100644 --- a/x/gov/simulation/msgs.go +++ b/x/gov/simulation/msgs.go @@ -35,11 +35,12 @@ func SimulateMsgSubmitProposal(k gov.Keeper, sk stake.Keeper) simulation.TestAnd ) require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() - pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) - sk.SetPool(ctx, pool) result := gov.NewHandler(k)(ctx, msg) if result.IsOK() { + // Update pool to keep invariants + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) + sk.SetPool(ctx, pool) write() } event(fmt.Sprintf("gov/MsgSubmitProposal/%v", result.IsOK())) @@ -62,10 +63,11 @@ func SimulateMsgDeposit(k gov.Keeper, sk stake.Keeper) simulation.TestAndRunTx { require.Nil(t, msg.ValidateBasic(), "expected msg to pass ValidateBasic: %s", msg.GetSignBytes()) ctx, write := ctx.CacheContext() result := gov.NewHandler(k)(ctx, msg) - pool := sk.GetPool(ctx) - pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) - sk.SetPool(ctx, pool) if result.IsOK() { + // Update pool to keep invariants + pool := sk.GetPool(ctx) + pool.LooseTokens = pool.LooseTokens.Sub(sdk.NewRatFromInt(deposit.AmountOf(denom))) + sk.SetPool(ctx, pool) write() } event(fmt.Sprintf("gov/MsgDeposit/%v", result.IsOK())) diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index 985a22dcac72..cd3a6a333d10 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -17,7 +17,7 @@ const ( evidenceFraction float64 = 0.01 // TODO Remove in favor of binary search for invariant violation - onOperation bool = false + onOperation bool = true ) var ( diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 5b332d5c21dd..b4dd3987a8c2 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -40,6 +40,7 @@ func SimulateFromSeed( // Setup event stats events := make(map[string]uint) event := func(what string) { + log += "\nevent - " + what events[what]++ } @@ -71,6 +72,8 @@ func SimulateFromSeed( // Run the BeginBlock handler app.BeginBlock(request) + log += "\nBeginBlock" + // Make sure invariants hold at beginning of block AssertAllInvariants(t, app, invariants, log) @@ -104,6 +107,11 @@ func SimulateFromSeed( header.Height++ header.Time = header.Time.Add(time.Duration(minTimePerBlock) * time.Second).Add(time.Duration(int64(r.Intn(int(timeDiff)))) * time.Second) + log += "\nEndBlock" + + // Make sure invariants hold at end of block + AssertAllInvariants(t, app, invariants, log) + // Generate a random RequestBeginBlock with the current validator set for the next block request = RandomRequestBeginBlock(t, r, validators, livenessTransitionMatrix, evidenceFraction, pastTimes, event, header, log) From 63762e9456b126a0356ed05b4f62cdc394544c6e Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 13 Aug 2018 14:26:59 +0200 Subject: [PATCH 53/63] Remove from CircleCI test_cover (why is this different) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 20e467f9eb73..b778653ead25 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -133,7 +133,7 @@ jobs: command: | export PATH="$GOBIN:$PATH" make install - for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | circleci tests split --split-by=timings); do + for pkg in $(go list github.com/cosmos/cosmos-sdk/... | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | grep -v '/simulation' | circleci tests split --split-by=timings); do id=$(basename "$pkg") GOCACHE=off go test -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" | tee "/tmp/logs/$id-$RANDOM.log" done From 70cc9bd641864988e953053d60c4cd82d4987e64 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 14:37:18 +0200 Subject: [PATCH 54/63] Update Gopkg.lock --- Gopkg.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index cc42ac4f4805..304f75d03e10 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" + digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" + digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" + digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" + digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,7 +165,7 @@ [[projects]] branch = "master" - digest = "1:8951fe6e358876736d8fa1f3992624fdbb2dec6bc49401c1381d1ef8abbb544f" + digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -262,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" + digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" + digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" + digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" + digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -340,11 +340,11 @@ [[projects]] branch = "master" - digest = "1:080e5f630945ad754f4b920e60b4d3095ba0237ebf88dc462eb28002932e3805" + digest = "1:8a020f916b23ff574845789daee6818daf8d25a4852419aae3f0b12378ba432a" name = "github.com/spf13/jwalterweatherman" packages = ["."] pruneopts = "UT" - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" + revision = "14d3d4c518341bea657dd8a226f5121c0ff8c9f2" [[projects]] digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" @@ -363,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" + digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" + digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -392,11 +392,11 @@ "leveldb/util", ] pruneopts = "UT" - revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" + revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd" [[projects]] branch = "master" - digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" + digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -423,7 +423,7 @@ version = "v0.9.2" [[projects]] - digest = "1:df232b6f3c44554161093af004100f75e564b398ad3ff63ecbc297fe400dcfdb" + digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -498,7 +498,7 @@ [[projects]] branch = "master" - digest = "1:3c3c47c1f7587c380afcc1d76385a4a03a2917b9ccc1ac50864d8f87e0264ada" + digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -520,7 +520,7 @@ revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] - digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" + digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -537,17 +537,17 @@ [[projects]] branch = "master" - digest = "1:a97b28c54844d6b9848a840ae83d4d263292e831e8c2a586116fcab5c7cfe5f2" + digest = "1:4bd75b1a219bc590b05c976bbebf47f4e993314ebb5c7cbf2efe05a09a184d54" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "98c5dad5d1a0e8a73845ecc8897d0bd56586511d" + revision = "14742f9018cd6651ec7364dc6ee08af0baaa1031" [[projects]] - digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -578,7 +578,7 @@ revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] - digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", From 44c5ae7b5d744c12ce43e1630c8e9a39cb430b64 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 20:01:56 +0200 Subject: [PATCH 55/63] Change timeout on 'make test_sim_gaia_fast' --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 825b0b4ce01e..ec99998d2066 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ test_sim_modules: test_sim_gaia_fast: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 2h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take several minutes..." From 4bd01b0d20ac4f2f306f2d1e5eda7f35837db0b2 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 23:05:02 +0200 Subject: [PATCH 56/63] testing... --- Makefile | 2 +- x/mock/simulation/constants.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ec99998d2066..d06d4eb4c8a4 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ test_sim_modules: test_sim_gaia_fast: @echo "Running full Gaia simulation. This may take several minutes..." - @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=200 -timeout 24h + @go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -v -timeout 24h test_sim_gaia_slow: @echo "Running full Gaia simulation. This may take several minutes..." diff --git a/x/mock/simulation/constants.go b/x/mock/simulation/constants.go index cd3a6a333d10..985a22dcac72 100644 --- a/x/mock/simulation/constants.go +++ b/x/mock/simulation/constants.go @@ -17,7 +17,7 @@ const ( evidenceFraction float64 = 0.01 // TODO Remove in favor of binary search for invariant violation - onOperation bool = true + onOperation bool = false ) var ( From 1e1f337a208137202e7ca183bfea2f6c68eda5e1 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 23:30:34 +0200 Subject: [PATCH 57/63] Some logs for stake bug --- x/stake/keeper/validator.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 8b8cea73d11c..5ce9303374bd 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -425,6 +425,7 @@ func (k Keeper) UpdateBondedValidators( panic("already decided to bond a validator, can't bond another!") } newValidatorBonded = true + fmt.Printf("Deciding to bond: %v\n", validator) } bondedValidatorsCount++ @@ -440,6 +441,8 @@ func (k Keeper) UpdateBondedValidators( iterator.Close() if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Owner) { + fmt.Printf("Validator: %v\n", validator) + fmt.Printf("Old cliff validator: %v\n", oldCliffValidatorAddr) panic("cliff validator has not been changed, yet we bonded a new validator") } From c13dd76c0ea02816822581706a29ba2578682833 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 15 Aug 2018 23:57:57 +0200 Subject: [PATCH 58/63] Add more debugging --- x/stake/keeper/slash.go | 2 ++ x/stake/keeper/validator.go | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index a741b5a85766..30dc904fd338 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -45,6 +45,8 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in } ownerAddress := validator.GetOwner() + fmt.Printf("Slashing validator with owner %X\n", ownerAddress) + // Track remaining slash amount for the validator // This will decrease when we slash unbondings and // redelegations, as that stake has since unbonded diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 5ce9303374bd..cd442990984a 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -388,6 +388,8 @@ func (k Keeper) UpdateBondedValidators( ctx sdk.Context, affectedValidator types.Validator) ( updatedVal types.Validator, updated bool) { + fmt.Printf("\nUpdateBondedValidators with validator %v\n", affectedValidator) + store := ctx.KVStore(k.storeKey) oldCliffValidatorAddr := k.GetCliffValidator(ctx) @@ -442,7 +444,8 @@ func (k Keeper) UpdateBondedValidators( if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Owner) { fmt.Printf("Validator: %v\n", validator) - fmt.Printf("Old cliff validator: %v\n", oldCliffValidatorAddr) + fmt.Printf("Old cliff validator: %X\n", oldCliffValidatorAddr) + fmt.Printf("Bonded validators count: %d of max %d\n", bondedValidatorsCount, maxValidators) panic("cliff validator has not been changed, yet we bonded a new validator") } From 93060d762d1c6991050eb35a3524cc6942e2efd7 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Thu, 16 Aug 2018 04:02:55 -0700 Subject: [PATCH 59/63] Make randomized simulation deterministic from a given seed (#2059) --- Gopkg.lock | 40 +++++++++---------- cmd/gaia/app/sim_test.go | 43 +++++++++++++++++++++ x/mock/app.go | 28 +++++++++++++- x/mock/simulation/random_simulate_blocks.go | 4 +- 4 files changed, 92 insertions(+), 23 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 304f75d03e10..1cdde264ff00 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" + digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" + digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" + digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" + digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,7 +165,7 @@ [[projects]] branch = "master" - digest = "1:12247a2e99a060cc692f6680e5272c8adf0b8f572e6bce0d7095e624c958a240" + digest = "1:ac64f01acc5eeea9dde40e326de6b6471e501392ec06524c3b51033aa50789bc" name = "github.com/hashicorp/hcl" packages = [ ".", @@ -262,7 +262,7 @@ version = "v1.0.0" [[projects]] - digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" + digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +273,7 @@ [[projects]] branch = "master" - digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" + digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +281,7 @@ [[projects]] branch = "master" - digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" + digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +293,7 @@ [[projects]] branch = "master" - digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" + digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +312,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" + digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +331,7 @@ version = "v1.2.0" [[projects]] - digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" + digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -363,7 +363,7 @@ version = "v1.0.0" [[projects]] - digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" + digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +375,7 @@ [[projects]] branch = "master" - digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" + digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -396,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" + digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -423,7 +423,7 @@ version = "v0.9.2" [[projects]] - digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" + digest = "1:df232b6f3c44554161093af004100f75e564b398ad3ff63ecbc297fe400dcfdb" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -498,7 +498,7 @@ [[projects]] branch = "master" - digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5" + digest = "1:3c3c47c1f7587c380afcc1d76385a4a03a2917b9ccc1ac50864d8f87e0264ada" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -520,7 +520,7 @@ revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] - digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" + digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" name = "golang.org/x/net" packages = [ "context", @@ -537,7 +537,7 @@ [[projects]] branch = "master" - digest = "1:4bd75b1a219bc590b05c976bbebf47f4e993314ebb5c7cbf2efe05a09a184d54" + digest = "1:1b9d0e0ed6a27439ded0a6cb25f8d46fb649910c6e1b3d2160eb54ee4d1249ab" name = "golang.org/x/sys" packages = [ "cpu", @@ -547,7 +547,7 @@ revision = "14742f9018cd6651ec7364dc6ee08af0baaa1031" [[projects]] - digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" name = "golang.org/x/text" packages = [ "collate", @@ -578,7 +578,7 @@ revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] - digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" + digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" name = "google.golang.org/grpc" packages = [ ".", diff --git a/cmd/gaia/app/sim_test.go b/cmd/gaia/app/sim_test.go index 18d3c809e825..5d0edcba2c7e 100644 --- a/cmd/gaia/app/sim_test.go +++ b/cmd/gaia/app/sim_test.go @@ -133,3 +133,46 @@ func TestFullGaiaSimulation(t *testing.T) { ) } + +// TODO: Make this not depend on Gaia or any of the modules, +// and place it in random_simulation_test.go +// +// Test doesn't use `app.ExportAppStateAndValidators` as that panics with the following: +// panic: Stored pool should not have been nil [recovered] +// panic: Stored pool should not have been nil +// Change to `app.ExportAppStateAndValidators` once it is fixed +func TestAppStateDeterminism(t *testing.T) { + numTimesToRun := 5 + appHashList := make([]json.RawMessage, numTimesToRun) + + seed := rand.Int63() + for i := 0; i < numTimesToRun; i++ { + logger := log.NewNopLogger() + db := dbm.NewMemDB() + app := NewGaiaApp(logger, db, nil) + + noOpInvariant := func(t *testing.T, baseapp *baseapp.BaseApp, log string) {} + noOpTestAndRunTx := 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) { + return "", nil + } + + // Run randomized simulation + simulation.SimulateFromSeed( + t, app.BaseApp, appStateFn, seed, + []simulation.TestAndRunTx{ + noOpTestAndRunTx, + }, + []simulation.RandSetup{}, + []simulation.Invariant{noOpInvariant}, + 0, + 10, + ) + appHash := app.LastCommitID().Hash + appHashList[i] = appHash + } + for i := 1; i < numTimesToRun; i++ { + require.Equal(t, appHashList[0], appHashList[i]) + } +} diff --git a/x/mock/app.go b/x/mock/app.go index 53b6345b0040..f472c5531cca 100644 --- a/x/mock/app.go +++ b/x/mock/app.go @@ -11,6 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" ) @@ -173,7 +174,32 @@ func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccA keys = make([]crypto.PrivKey, n, n) addrs = make([]sdk.AccAddress, n, n) for i := 0; i < n; i++ { - keys[i] = ed25519.GenPrivKey() + if rand.Int63()%2 == 0 { + keys[i] = secp256k1.GenPrivKey() + } else { + keys[i] = ed25519.GenPrivKey() + } + addrs[i] = sdk.AccAddress(keys[i].PubKey().Address()) + } + return +} + +// GeneratePrivKeyAddressPairsFromRand generates a total of n private key, address +// pairs using the provided randomness source. +func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) { + keys = make([]crypto.PrivKey, n, n) + addrs = make([]sdk.AccAddress, n, n) + for i := 0; i < n; i++ { + secret := make([]byte, 32) + _, err := rand.Read(secret) + if err != nil { + panic("Could not read randomness") + } + if rand.Int63()%2 == 0 { + keys[i] = secp256k1.GenPrivKeySecp256k1(secret) + } else { + keys[i] = ed25519.GenPrivKeyFromSecret(secret) + } addrs[i] = sdk.AccAddress(keys[i].PubKey().Address()) } return diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index b4dd3987a8c2..2aa1a7b0e812 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -34,8 +34,8 @@ func SimulateFromSeed( ) { log := fmt.Sprintf("Starting SimulateFromSeed with randomness created with seed %d", int(seed)) fmt.Printf("%s\n", log) - keys, accs := mock.GeneratePrivKeyAddressPairs(numKeys) r := rand.New(rand.NewSource(seed)) + keys, accs := mock.GeneratePrivKeyAddressPairsFromRand(r, numKeys) // Setup event stats events := make(map[string]uint) @@ -119,7 +119,7 @@ func SimulateFromSeed( validators = updateValidators(t, r, validators, res.ValidatorUpdates, event) } - fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %d\n", header.Height, header.Time) + fmt.Printf("\nSimulation complete. Final height (blocks): %d, final time (seconds): %v\n", header.Height, header.Time) DisplayEvents(events) } From 54ee4969ab98b1b2a435892c67d86e063b30c711 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 16 Aug 2018 13:27:15 +0200 Subject: [PATCH 60/63] Update Gopkg.lock --- Gopkg.lock | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 1cdde264ff00..c3a540858e7a 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,7 +34,7 @@ [[projects]] branch = "master" - digest = "1:6aabc1566d6351115d561d038da82a4c19b46c3b6e17f4a0a2fa60260663dc79" + digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8" name = "github.com/btcsuite/btcd" packages = ["btcec"] pruneopts = "UT" @@ -71,7 +71,7 @@ version = "v1.4.7" [[projects]] - digest = "1:fa30c0652956e159cdb97dcb2ef8b8db63ed668c02a5c3a40961c8f0641252fe" + digest = "1:fdf5169073fb0ad6dc12a70c249145e30f4058647bea25f0abd48b6d9f228a11" name = "github.com/go-kit/kit" packages = [ "log", @@ -103,7 +103,7 @@ version = "v1.7.0" [[projects]] - digest = "1:212285efb97b9ec2e20550d81f0446cb7897e57cbdfd7301b1363ab113d8be45" + digest = "1:35621fe20f140f05a0c4ef662c26c0ab4ee50bca78aa30fe87d33120bd28165e" name = "github.com/gogo/protobuf" packages = [ "gogoproto", @@ -118,7 +118,7 @@ version = "v1.1.1" [[projects]] - digest = "1:cb22af0ed7c72d495d8be1106233ee553898950f15fd3f5404406d44c2e86888" + digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" name = "github.com/golang/protobuf" packages = [ "proto", @@ -165,12 +165,13 @@ [[projects]] branch = "master" - digest = "1:ac64f01acc5eeea9dde40e326de6b6471e501392ec06524c3b51033aa50789bc" + digest = "1:a361611b8c8c75a1091f00027767f7779b29cb37c456a71b8f2604c88057ab40" name = "github.com/hashicorp/hcl" packages = [ ".", "hcl/ast", "hcl/parser", + "hcl/printer", "hcl/scanner", "hcl/strconv", "hcl/token", @@ -262,7 +263,7 @@ version = "v1.0.0" [[projects]] - digest = "1:98225904b7abff96c052b669b25788f18225a36673fba022fb93514bb9a2a64e" + digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0" name = "github.com/prometheus/client_golang" packages = [ "prometheus", @@ -273,7 +274,7 @@ [[projects]] branch = "master" - digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" + digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4" name = "github.com/prometheus/client_model" packages = ["go"] pruneopts = "UT" @@ -281,7 +282,7 @@ [[projects]] branch = "master" - digest = "1:dad2e5a2153ee7a6c9ab8fc13673a16ee4fb64434a7da980965a3741b0c981a3" + digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5" name = "github.com/prometheus/common" packages = [ "expfmt", @@ -293,7 +294,7 @@ [[projects]] branch = "master" - digest = "1:a37c98f4b7a66bb5c539c0539f0915a74ef1c8e0b3b6f45735289d94cae92bfd" + digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290" name = "github.com/prometheus/procfs" packages = [ ".", @@ -312,7 +313,7 @@ revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[projects]] - digest = "1:37ace7f35375adec11634126944bdc45a673415e2fcc07382d03b75ec76ea94c" + digest = "1:bd1ae00087d17c5a748660b8e89e1043e1e5479d0fea743352cda2f8dd8c4f84" name = "github.com/spf13/afero" packages = [ ".", @@ -331,7 +332,7 @@ version = "v1.2.0" [[projects]] - digest = "1:627ab2f549a6a55c44f46fa24a4307f4d0da81bfc7934ed0473bf38b24051d26" + digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e" name = "github.com/spf13/cobra" packages = ["."] pruneopts = "UT" @@ -363,7 +364,7 @@ version = "v1.0.0" [[projects]] - digest = "1:73697231b93fb74a73ebd8384b68b9a60c57ea6b13c56d2425414566a72c8e6d" + digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6" name = "github.com/stretchr/testify" packages = [ "assert", @@ -375,7 +376,7 @@ [[projects]] branch = "master" - digest = "1:922191411ad8f61bcd8018ac127589bb489712c1d1a0ab2497aca4b16de417d2" + digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5" name = "github.com/syndtr/goleveldb" packages = [ "leveldb", @@ -396,7 +397,7 @@ [[projects]] branch = "master" - digest = "1:203b409c21115233a576f99e8f13d8e07ad82b25500491f7e1cca12588fb3232" + digest = "1:087aaa7920e5d0bf79586feb57ce01c35c830396ab4392798112e8aae8c47722" name = "github.com/tendermint/ed25519" packages = [ ".", @@ -423,7 +424,7 @@ version = "v0.9.2" [[projects]] - digest = "1:df232b6f3c44554161093af004100f75e564b398ad3ff63ecbc297fe400dcfdb" + digest = "1:26146cdb2811ce481e72138439b9b1aa17a64d54364f96bb92f97a9ef8ba4f01" name = "github.com/tendermint/tendermint" packages = [ "abci/client", @@ -498,7 +499,7 @@ [[projects]] branch = "master" - digest = "1:3c3c47c1f7587c380afcc1d76385a4a03a2917b9ccc1ac50864d8f87e0264ada" + digest = "1:7a71fffde456d746c52f9cd09c50b034533a3180fb1f6320abb149f2ccc579e5" name = "golang.org/x/crypto" packages = [ "blowfish", @@ -520,7 +521,7 @@ revision = "de0752318171da717af4ce24d0a2e8626afaeb11" [[projects]] - digest = "1:04dda8391c3e2397daf254ac68003f30141c069b228d06baec8324a5f81dc1e9" + digest = "1:d36f55a999540d29b6ea3c2ea29d71c76b1d9853fdcd3e5c5cb4836f2ba118f1" name = "golang.org/x/net" packages = [ "context", @@ -537,17 +538,17 @@ [[projects]] branch = "master" - digest = "1:1b9d0e0ed6a27439ded0a6cb25f8d46fb649910c6e1b3d2160eb54ee4d1249ab" + digest = "1:a989b95f72fce8876213e8e20492525b4cf69a9e7fee7f1d9897983ee0d547e9" name = "golang.org/x/sys" packages = [ "cpu", "unix", ] pruneopts = "UT" - revision = "14742f9018cd6651ec7364dc6ee08af0baaa1031" + revision = "1c9583448a9c3aa0f9a6a5241bf73c0bd8aafded" [[projects]] - digest = "1:7509ba4347d1f8de6ae9be8818b0cd1abc3deeffe28aeaf4be6d4b6b5178d9ca" + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" name = "golang.org/x/text" packages = [ "collate", @@ -575,10 +576,10 @@ name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] pruneopts = "UT" - revision = "383e8b2c3b9e36c4076b235b32537292176bae20" + revision = "d0a8f471bba2dbb160885b0000d814ee5d559bad" [[projects]] - digest = "1:4515e3030c440845b046354fd5d57671238428b820deebce2e9dabb5cd3c51ac" + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" name = "google.golang.org/grpc" packages = [ ".", From 617a5032ccf9a80517bb8d36bd6a03f8721f136b Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 16 Aug 2018 13:50:20 +0200 Subject: [PATCH 61/63] Zero inflation on stake module test; additional event --- x/mock/simulation/random_simulate_blocks.go | 3 ++- x/stake/simulation/msgs.go | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x/mock/simulation/random_simulate_blocks.go b/x/mock/simulation/random_simulate_blocks.go index 2aa1a7b0e812..1b695363122f 100644 --- a/x/mock/simulation/random_simulate_blocks.go +++ b/x/mock/simulation/random_simulate_blocks.go @@ -156,7 +156,7 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m i++ } evidence := make([]abci.Evidence, 0) - if r.Float64() < evidenceFraction { + for r.Float64() < evidenceFraction { height := header.Height time := header.Time if r.Float64() < pastEvidenceFraction { @@ -175,6 +175,7 @@ func RandomRequestBeginBlock(t *testing.T, r *rand.Rand, validators map[string]m Time: time, TotalVotingPower: currentTotalVotingPower, }) + event("beginblock/evidence") } return abci.RequestBeginBlock{ Header: header, diff --git a/x/stake/simulation/msgs.go b/x/stake/simulation/msgs.go index e4077a7497ce..ec39f87b012c 100644 --- a/x/stake/simulation/msgs.go +++ b/x/stake/simulation/msgs.go @@ -235,7 +235,10 @@ func SimulateMsgCompleteRedelegate(k stake.Keeper) simulation.TestAndRunTx { func Setup(mapp *mock.App, k stake.Keeper) simulation.RandSetup { return func(r *rand.Rand, privKeys []crypto.PrivKey) { ctx := mapp.NewContext(false, abci.Header{}) - stake.InitGenesis(ctx, k, stake.DefaultGenesisState()) + gen := stake.DefaultGenesisState() + gen.Params.InflationMax = sdk.NewRat(0) + gen.Params.InflationMin = sdk.NewRat(0) + stake.InitGenesis(ctx, k, gen) params := k.GetParams(ctx) denom := params.BondDenom loose := sdk.ZeroInt() From 169260ff6ac7160c3f293f76d69eeabf42fa6e62 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 16 Aug 2018 13:58:41 +0200 Subject: [PATCH 62/63] Remove accidental change from develop --- docs/install.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/install.md diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 000000000000..bafdfc4bdeb9 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,59 @@ +# Install + +The fastest and easiest way to install the Cosmos SDK binaries +is to run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_ubuntu.sh) on a fresh Ubuntu instance. Similarly, you can run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_bsd.sh) on a fresh FreeBSD instance. Read the scripts before running them to ensure no untrusted connection is being made, for example we're making curl requests to download golang. Also read the comments / instructions carefully (i.e., reset your terminal after running the script). + +Cosmos SDK can be installed to +`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program: + +``` +go get github.com/cosmos/cosmos-sdk +``` + +If the dependencies have been updated with breaking changes, or if +another branch is required, `dep` is used for dependency management. +Thus, assuming you've already run `go get` or otherwise cloned the repo, +the correct way to install is: + +``` +cd $GOPATH/src/github.com/cosmos/cosmos-sdk +make get_tools +make get_vendor_deps +make install +make install_examples +``` + +This will install `gaiad` and `gaiacli` and four example binaries: +`basecoind`, `basecli`, `democoind`, and `democli`. + +Verify that everything is OK by running: + +``` +gaiad version +``` + +you should see: + +``` +0.17.3-a5a78eb +``` + +then with: + +``` +gaiacli version +``` +you should see the same version (or a later one for both). + +## Update + +Get latest code (you can also `git fetch` only the version desired), +ensure the dependencies are up to date, then recompile. + +``` +cd $GOPATH/src/github.com/cosmos/cosmos-sdk +git fetch -a origin +git checkout VERSION +make get_vendor_deps +make install +``` From eb3e623d0d148f70dfbc520ccc6a17c2b546a376 Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Thu, 16 Aug 2018 16:25:57 +0200 Subject: [PATCH 63/63] Remove printfs for merge into release/v0.24.0 --- x/stake/keeper/slash.go | 2 -- x/stake/keeper/validator.go | 6 ------ 2 files changed, 8 deletions(-) diff --git a/x/stake/keeper/slash.go b/x/stake/keeper/slash.go index 30dc904fd338..a741b5a85766 100644 --- a/x/stake/keeper/slash.go +++ b/x/stake/keeper/slash.go @@ -45,8 +45,6 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in } ownerAddress := validator.GetOwner() - fmt.Printf("Slashing validator with owner %X\n", ownerAddress) - // Track remaining slash amount for the validator // This will decrease when we slash unbondings and // redelegations, as that stake has since unbonded diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index cd442990984a..8b8cea73d11c 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -388,8 +388,6 @@ func (k Keeper) UpdateBondedValidators( ctx sdk.Context, affectedValidator types.Validator) ( updatedVal types.Validator, updated bool) { - fmt.Printf("\nUpdateBondedValidators with validator %v\n", affectedValidator) - store := ctx.KVStore(k.storeKey) oldCliffValidatorAddr := k.GetCliffValidator(ctx) @@ -427,7 +425,6 @@ func (k Keeper) UpdateBondedValidators( panic("already decided to bond a validator, can't bond another!") } newValidatorBonded = true - fmt.Printf("Deciding to bond: %v\n", validator) } bondedValidatorsCount++ @@ -443,9 +440,6 @@ func (k Keeper) UpdateBondedValidators( iterator.Close() if newValidatorBonded && bytes.Equal(oldCliffValidatorAddr, validator.Owner) { - fmt.Printf("Validator: %v\n", validator) - fmt.Printf("Old cliff validator: %X\n", oldCliffValidatorAddr) - fmt.Printf("Bonded validators count: %d of max %d\n", bondedValidatorsCount, maxValidators) panic("cliff validator has not been changed, yet we bonded a new validator") }