2018-07-17 14:06:30 -07:00
package app
2018-07-11 15:14:37 -07:00
import (
2018-07-17 15:04:10 -07:00
"encoding/json"
2018-07-18 23:40:46 -07:00
"flag"
2018-09-01 19:04:44 -07:00
"fmt"
2018-10-29 16:10:39 -07:00
"io/ioutil"
2018-07-17 15:04:10 -07:00
"math/rand"
2018-08-30 11:43:56 -07:00
"os"
2018-07-11 15:14:37 -07:00
"testing"
2018-11-04 20:44:43 -08:00
"time"
2018-07-11 15:14:37 -07:00
"github.com/stretchr/testify/require"
2018-07-12 13:01:43 -07:00
2018-11-08 16:28:28 -08:00
abci "github.com/tendermint/tendermint/abci/types"
2018-07-12 13:01:43 -07:00
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
2018-11-27 00:14:22 -08:00
"github.com/cosmos/cosmos-sdk/baseapp"
2018-07-17 15:04:10 -07:00
sdk "github.com/cosmos/cosmos-sdk/types"
2018-10-22 21:53:06 -07:00
authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation"
2018-07-18 00:05:48 -07:00
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
2018-10-05 17:32:06 -07:00
distr "github.com/cosmos/cosmos-sdk/x/distribution"
2018-10-23 11:33:39 -07:00
distrsim "github.com/cosmos/cosmos-sdk/x/distribution/simulation"
2018-08-31 21:57:33 -07:00
"github.com/cosmos/cosmos-sdk/x/gov"
2018-08-16 08:36:15 -07:00
govsim "github.com/cosmos/cosmos-sdk/x/gov/simulation"
2018-10-19 11:36:00 -07:00
"github.com/cosmos/cosmos-sdk/x/mint"
2018-07-16 18:25:15 -07:00
"github.com/cosmos/cosmos-sdk/x/mock/simulation"
2018-08-31 02:03:43 -07:00
"github.com/cosmos/cosmos-sdk/x/slashing"
2018-08-16 08:36:15 -07:00
slashingsim "github.com/cosmos/cosmos-sdk/x/slashing/simulation"
2018-07-17 11:33:53 -07:00
stake "github.com/cosmos/cosmos-sdk/x/stake"
2018-07-17 15:04:10 -07:00
stakesim "github.com/cosmos/cosmos-sdk/x/stake/simulation"
2018-11-12 10:54:18 -08:00
stakeTypes "github.com/cosmos/cosmos-sdk/x/stake/types"
2018-07-16 18:15:50 -07:00
)
2018-07-18 23:40:46 -07:00
var (
2018-09-01 12:32:24 -07:00
seed int64
numBlocks int
blockSize int
enabled bool
verbose bool
commit bool
2018-11-29 07:17:10 -08:00
period int
2018-07-11 15:14:37 -07:00
)
2018-07-18 23:40:46 -07:00
func init ( ) {
flag . Int64Var ( & seed , "SimulationSeed" , 42 , "Simulation random seed" )
2018-08-16 08:36:15 -07:00
flag . IntVar ( & numBlocks , "SimulationNumBlocks" , 500 , "Number of blocks" )
flag . IntVar ( & blockSize , "SimulationBlockSize" , 200 , "Operations per block" )
2018-07-18 23:40:46 -07:00
flag . BoolVar ( & enabled , "SimulationEnabled" , false , "Enable the simulation" )
2018-08-16 08:36:15 -07:00
flag . BoolVar ( & verbose , "SimulationVerbose" , false , "Verbose log output" )
2018-08-30 11:47:32 -07:00
flag . BoolVar ( & commit , "SimulationCommit" , false , "Have the simulation commit" )
2018-11-29 07:17:10 -08:00
flag . IntVar ( & period , "SimulationPeriod" , 100 , "Run slow invariants only once every period assertions" )
2018-07-18 23:40:46 -07:00
}
2018-09-22 20:20:53 -07:00
func appStateFn ( r * rand . Rand , accs [ ] simulation . Account ) json . RawMessage {
2018-07-17 15:04:10 -07:00
var genesisAccounts [ ] GenesisAccount
2018-07-17 11:33:53 -07:00
2018-11-04 20:44:43 -08:00
amount := int64 ( r . Intn ( 1e6 ) )
numInitiallyBonded := int64 ( r . Intn ( 250 ) )
numAccs := int64 ( len ( accs ) )
if numInitiallyBonded > numAccs {
numInitiallyBonded = numAccs
}
2018-11-26 04:13:47 -08:00
fmt . Printf ( "Selected randomly generated parameters for simulated genesis:\n" +
"\t{amount of steak per account: %v, initially bonded validators: %v}\n" ,
amount , numInitiallyBonded )
2018-10-23 09:24:06 -07:00
2018-07-17 15:04:10 -07:00
// Randomly generate some genesis accounts
2018-08-16 08:36:15 -07:00
for _ , acc := range accs {
2018-11-20 01:22:35 -08:00
coins := sdk . Coins { sdk . NewCoin ( stakeTypes . DefaultBondDenom , sdk . NewInt ( amount ) ) }
2018-07-17 15:04:10 -07:00
genesisAccounts = append ( genesisAccounts , GenesisAccount {
2018-09-22 20:20:53 -07:00
Address : acc . Address ,
2018-07-17 15:04:10 -07:00
Coins : coins ,
} )
}
2018-10-05 17:32:06 -07:00
2018-11-04 20:44:43 -08:00
// Random genesis states
govGenesis := gov . GenesisState {
2018-11-06 23:33:18 -08:00
StartingProposalID : uint64 ( r . Intn ( 100 ) ) ,
DepositParams : gov . DepositParams {
2018-11-12 10:54:18 -08:00
MinDeposit : sdk . Coins { sdk . NewInt64Coin ( stakeTypes . DefaultBondDenom , int64 ( r . Intn ( 1e3 ) ) ) } ,
2018-11-04 20:44:43 -08:00
MaxDepositPeriod : time . Duration ( r . Intn ( 2 * 172800 ) ) * time . Second ,
} ,
2018-11-06 23:33:18 -08:00
VotingParams : gov . VotingParams {
2018-11-04 20:44:43 -08:00
VotingPeriod : time . Duration ( r . Intn ( 2 * 172800 ) ) * time . Second ,
} ,
2018-11-06 23:33:18 -08:00
TallyParams : gov . TallyParams {
2018-11-04 20:44:43 -08:00
Threshold : sdk . NewDecWithPrec ( 5 , 1 ) ,
Veto : sdk . NewDecWithPrec ( 334 , 3 ) ,
GovernancePenalty : sdk . NewDecWithPrec ( 1 , 2 ) ,
} ,
}
2018-11-26 04:13:47 -08:00
fmt . Printf ( "Selected randomly generated governance parameters:\n\t%+v\n" , govGenesis )
2018-11-04 20:44:43 -08:00
stakeGenesis := stake . GenesisState {
Pool : stake . InitialPool ( ) ,
Params : stake . Params {
UnbondingTime : time . Duration ( r . Intn ( 60 * 60 * 24 * 3 * 2 ) ) * time . Second ,
MaxValidators : uint16 ( r . Intn ( 250 ) ) ,
2018-11-12 10:54:18 -08:00
BondDenom : stakeTypes . DefaultBondDenom ,
2018-11-04 20:44:43 -08:00
} ,
}
2018-11-26 04:13:47 -08:00
fmt . Printf ( "Selected randomly generated staking parameters:\n\t%+v\n" , stakeGenesis )
2018-11-04 20:44:43 -08:00
slashingGenesis := slashing . GenesisState {
Params : slashing . Params {
MaxEvidenceAge : stakeGenesis . Params . UnbondingTime ,
DoubleSignUnbondDuration : time . Duration ( r . Intn ( 60 * 60 * 24 ) ) * time . Second ,
SignedBlocksWindow : int64 ( r . Intn ( 1000 ) ) ,
DowntimeUnbondDuration : time . Duration ( r . Intn ( 86400 ) ) * time . Second ,
MinSignedPerWindow : sdk . NewDecWithPrec ( int64 ( r . Intn ( 10 ) ) , 1 ) ,
SlashFractionDoubleSign : sdk . NewDec ( 1 ) . Quo ( sdk . NewDec ( int64 ( r . Intn ( 50 ) + 1 ) ) ) ,
SlashFractionDowntime : sdk . NewDec ( 1 ) . Quo ( sdk . NewDec ( int64 ( r . Intn ( 200 ) + 1 ) ) ) ,
} ,
}
2018-11-26 04:13:47 -08:00
fmt . Printf ( "Selected randomly generated slashing parameters:\n\t%+v\n" , slashingGenesis )
2018-11-04 20:44:43 -08:00
mintGenesis := mint . GenesisState {
2018-11-26 04:13:47 -08:00
Minter : mint . InitialMinter (
sdk . NewDecWithPrec ( int64 ( r . Intn ( 99 ) ) , 2 ) ) ,
Params : mint . NewParams (
stakeTypes . DefaultBondDenom ,
sdk . NewDecWithPrec ( int64 ( r . Intn ( 99 ) ) , 2 ) ,
sdk . NewDecWithPrec ( 20 , 2 ) ,
sdk . NewDecWithPrec ( 7 , 2 ) ,
sdk . NewDecWithPrec ( 67 , 2 ) ,
uint64 ( 60 * 60 * 8766 / 5 ) ) ,
2018-11-04 20:44:43 -08:00
}
2018-11-26 04:13:47 -08:00
fmt . Printf ( "Selected randomly generated minting parameters:\n\t%+v\n" , mintGenesis )
2018-08-16 08:36:15 -07:00
var validators [ ] stake . Validator
var delegations [ ] stake . Delegation
2018-10-05 17:32:06 -07:00
valAddrs := make ( [ ] sdk . ValAddress , numInitiallyBonded )
2018-08-16 08:36:15 -07:00
for i := 0 ; i < int ( numInitiallyBonded ) ; i ++ {
2018-10-05 17:32:06 -07:00
valAddr := sdk . ValAddress ( accs [ i ] . Address )
valAddrs [ i ] = valAddr
validator := stake . NewValidator ( valAddr , accs [ i ] . PubKey , stake . Description { } )
2018-11-04 20:44:43 -08:00
validator . Tokens = sdk . NewDec ( amount )
validator . DelegatorShares = sdk . NewDec ( amount )
2018-11-26 04:21:23 -08:00
delegation := stake . Delegation { accs [ i ] . Address , valAddr , sdk . NewDec ( amount ) }
2018-08-16 08:36:15 -07:00
validators = append ( validators , validator )
delegations = append ( delegations , delegation )
}
2018-11-04 20:44:43 -08:00
stakeGenesis . Pool . LooseTokens = sdk . NewDec ( ( amount * numAccs ) + ( numInitiallyBonded * amount ) )
2018-08-16 08:36:15 -07:00
stakeGenesis . Validators = validators
stakeGenesis . Bonds = delegations
2018-10-05 17:32:06 -07:00
2018-07-17 14:06:30 -07:00
genesis := GenesisState {
2018-08-31 02:03:43 -07:00
Accounts : genesisAccounts ,
StakeData : stakeGenesis ,
2018-10-19 11:36:00 -07:00
MintData : mintGenesis ,
2018-10-14 23:43:36 -07:00
DistrData : distr . DefaultGenesisWithValidators ( valAddrs ) ,
2018-10-06 09:08:49 -07:00
SlashingData : slashingGenesis ,
2018-08-31 02:03:43 -07:00
GovData : govGenesis ,
2018-07-17 11:33:53 -07:00
}
// Marshal genesis
2018-07-17 14:06:30 -07:00
appState , err := MakeCodec ( ) . MarshalJSON ( genesis )
2018-07-17 11:33:53 -07:00
if err != nil {
panic ( err )
}
2018-07-17 15:04:10 -07:00
return appState
}
2018-09-12 00:16:52 -07:00
func testAndRunTxs ( app * GaiaApp ) [ ] simulation . WeightedOperation {
return [ ] simulation . WeightedOperation {
2018-10-23 08:54:58 -07:00
{ 5 , authsim . SimulateDeductFee ( app . accountKeeper , app . feeCollectionKeeper ) } ,
2018-10-20 23:22:48 -07:00
{ 100 , banksim . SingleInputSendMsg ( app . accountKeeper , app . bankKeeper ) } ,
2018-10-23 11:33:39 -07:00
{ 50 , distrsim . SimulateMsgSetWithdrawAddress ( app . accountKeeper , app . distrKeeper ) } ,
{ 50 , distrsim . SimulateMsgWithdrawDelegatorRewardsAll ( app . accountKeeper , app . distrKeeper ) } ,
{ 50 , distrsim . SimulateMsgWithdrawDelegatorReward ( app . accountKeeper , app . distrKeeper ) } ,
{ 50 , distrsim . SimulateMsgWithdrawValidatorRewardsAll ( app . accountKeeper , app . distrKeeper ) } ,
2018-10-22 21:53:06 -07:00
{ 5 , govsim . SimulateSubmittingVotingAndSlashingForProposal ( app . govKeeper , app . stakeKeeper ) } ,
2018-11-06 23:33:18 -08:00
{ 100 , govsim . SimulateMsgDeposit ( app . govKeeper ) } ,
2018-10-20 23:22:48 -07:00
{ 100 , stakesim . SimulateMsgCreateValidator ( app . accountKeeper , app . stakeKeeper ) } ,
2018-10-22 21:53:06 -07:00
{ 5 , stakesim . SimulateMsgEditValidator ( app . stakeKeeper ) } ,
2018-10-20 23:22:48 -07:00
{ 100 , stakesim . SimulateMsgDelegate ( app . accountKeeper , app . stakeKeeper ) } ,
{ 100 , stakesim . SimulateMsgBeginUnbonding ( app . accountKeeper , app . stakeKeeper ) } ,
{ 100 , stakesim . SimulateMsgBeginRedelegate ( app . accountKeeper , app . stakeKeeper ) } ,
2018-09-12 00:16:52 -07:00
{ 100 , slashingsim . SimulateMsgUnjail ( app . slashingKeeper ) } ,
2018-08-17 07:19:33 -07:00
}
}
func invariants ( app * GaiaApp ) [ ] simulation . Invariant {
return [ ] simulation . Invariant {
2018-11-29 07:17:10 -08:00
simulation . PeriodicInvariant ( banksim . NonnegativeBalanceInvariant ( app . accountKeeper ) , period , 0 ) ,
simulation . PeriodicInvariant ( govsim . AllInvariants ( ) , period , 0 ) ,
simulation . PeriodicInvariant ( distrsim . AllInvariants ( app . distrKeeper , app . stakeKeeper ) , period , 0 ) ,
simulation . PeriodicInvariant ( stakesim . AllInvariants ( app . bankKeeper , app . stakeKeeper ,
app . feeCollectionKeeper , app . distrKeeper , app . accountKeeper ) , period , 0 ) ,
simulation . PeriodicInvariant ( slashingsim . AllInvariants ( ) , period , 0 ) ,
2018-08-17 07:19:33 -07:00
}
}
2018-11-27 00:14:22 -08:00
// Pass this in as an option to use a dbStoreAdapter instead of an IAVLStore for simulation speed.
func fauxMerkleModeOpt ( bapp * baseapp . BaseApp ) {
bapp . SetFauxMerkleMode ( )
}
2018-08-29 23:02:15 -07:00
// Profile with:
2018-09-01 19:04:44 -07:00
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -SimulationCommit=true -cpuprofile cpu.out
2018-08-29 23:02:15 -07:00
func BenchmarkFullGaiaSimulation ( b * testing . B ) {
// Setup Gaia application
var logger log . Logger
logger = log . NewNopLogger ( )
2018-08-30 11:43:56 -07:00
var db dbm . DB
2018-10-29 16:10:39 -07:00
dir , _ := ioutil . TempDir ( "" , "goleveldb-gaia-sim" )
2018-09-01 12:32:24 -07:00
db , _ = dbm . NewGoLevelDB ( "Simulation" , dir )
defer func ( ) {
db . Close ( )
os . RemoveAll ( dir )
} ( )
2018-08-29 23:02:15 -07:00
app := NewGaiaApp ( logger , db , nil )
// Run randomized simulation
// TODO parameterize numbers, save for a later PR
2018-11-26 04:21:23 -08:00
_ , err := simulation . SimulateFromSeed (
2018-08-29 23:02:15 -07:00
b , app . BaseApp , appStateFn , seed ,
testAndRunTxs ( app ) ,
2018-08-30 00:13:31 -07:00
invariants ( app ) , // these shouldn't get ran
2018-09-01 19:04:44 -07:00
numBlocks ,
2018-08-31 21:57:33 -07:00
blockSize ,
2018-08-30 11:47:32 -07:00
commit ,
2018-08-29 23:02:15 -07:00
)
2018-09-11 02:18:58 -07:00
if err != nil {
fmt . Println ( err )
b . Fail ( )
}
2018-09-01 19:04:44 -07:00
if commit {
fmt . Println ( "GoLevelDB Stats" )
fmt . Println ( db . Stats ( ) [ "leveldb.stats" ] )
fmt . Println ( "GoLevelDB cached block size" , db . Stats ( ) [ "leveldb.cachedblock" ] )
}
2018-08-29 23:02:15 -07:00
}
2018-07-17 15:04:10 -07:00
func TestFullGaiaSimulation ( t * testing . T ) {
2018-07-18 23:40:46 -07:00
if ! enabled {
2018-07-17 15:04:10 -07:00
t . Skip ( "Skipping Gaia simulation" )
}
// Setup Gaia application
2018-08-16 08:36:15 -07:00
var logger log . Logger
if verbose {
logger = log . TestingLogger ( )
} else {
logger = log . NewNopLogger ( )
}
2018-10-29 16:10:39 -07:00
var db dbm . DB
dir , _ := ioutil . TempDir ( "" , "goleveldb-gaia-sim" )
db , _ = dbm . NewGoLevelDB ( "Simulation" , dir )
defer func ( ) {
db . Close ( )
os . RemoveAll ( dir )
} ( )
2018-11-27 00:14:22 -08:00
app := NewGaiaApp ( logger , db , nil , fauxMerkleModeOpt )
2018-07-17 15:04:10 -07:00
require . Equal ( t , "GaiaApp" , app . Name ( ) )
2018-07-16 18:15:50 -07:00
// Run randomized simulation
2018-11-26 04:21:23 -08:00
_ , err := simulation . SimulateFromSeed (
2018-07-17 22:37:38 -07:00
t , app . BaseApp , appStateFn , seed ,
2018-08-17 07:19:33 -07:00
testAndRunTxs ( app ) ,
invariants ( app ) ,
2018-07-18 23:40:46 -07:00
numBlocks ,
2018-07-18 00:54:41 -07:00
blockSize ,
2018-08-30 11:47:32 -07:00
commit ,
2018-07-16 18:15:50 -07:00
)
2018-09-01 19:04:44 -07:00
if commit {
2018-10-29 16:10:39 -07:00
// for memdb:
// fmt.Println("Database Size", db.Stats()["database.size"])
fmt . Println ( "GoLevelDB Stats" )
fmt . Println ( db . Stats ( ) [ "leveldb.stats" ] )
fmt . Println ( "GoLevelDB cached block size" , db . Stats ( ) [ "leveldb.cachedblock" ] )
2018-09-01 19:04:44 -07:00
}
2018-09-11 02:18:58 -07:00
require . Nil ( t , err )
2018-07-11 15:14:37 -07:00
}
2018-08-16 08:36:15 -07:00
2018-11-08 16:28:28 -08:00
func TestGaiaImportExport ( t * testing . T ) {
if ! enabled {
t . Skip ( "Skipping Gaia import/export simulation" )
}
// Setup Gaia application
var logger log . Logger
if verbose {
logger = log . TestingLogger ( )
} else {
logger = log . NewNopLogger ( )
}
var db dbm . DB
dir , _ := ioutil . TempDir ( "" , "goleveldb-gaia-sim" )
db , _ = dbm . NewGoLevelDB ( "Simulation" , dir )
defer func ( ) {
db . Close ( )
os . RemoveAll ( dir )
} ( )
2018-11-27 00:14:22 -08:00
app := NewGaiaApp ( logger , db , nil , fauxMerkleModeOpt )
2018-11-08 16:28:28 -08:00
require . Equal ( t , "GaiaApp" , app . Name ( ) )
// Run randomized simulation
2018-11-26 04:21:23 -08:00
_ , err := simulation . SimulateFromSeed (
2018-11-08 16:28:28 -08:00
t , app . BaseApp , appStateFn , seed ,
testAndRunTxs ( app ) ,
invariants ( app ) ,
numBlocks ,
blockSize ,
commit ,
)
if commit {
// for memdb:
// fmt.Println("Database Size", db.Stats()["database.size"])
fmt . Println ( "GoLevelDB Stats" )
fmt . Println ( db . Stats ( ) [ "leveldb.stats" ] )
fmt . Println ( "GoLevelDB cached block size" , db . Stats ( ) [ "leveldb.cachedblock" ] )
}
require . Nil ( t , err )
fmt . Printf ( "Exporting genesis...\n" )
2018-11-26 04:21:23 -08:00
appState , _ , err := app . ExportAppStateAndValidators ( false )
2018-11-08 16:28:28 -08:00
if err != nil {
panic ( err )
}
fmt . Printf ( "Importing genesis...\n" )
newDir , _ := ioutil . TempDir ( "" , "goleveldb-gaia-sim-2" )
newDB , _ := dbm . NewGoLevelDB ( "Simulation-2" , dir )
defer func ( ) {
newDB . Close ( )
os . RemoveAll ( newDir )
} ( )
2018-11-27 00:14:22 -08:00
newApp := NewGaiaApp ( log . NewNopLogger ( ) , newDB , nil , fauxMerkleModeOpt )
2018-11-08 16:28:28 -08:00
require . Equal ( t , "GaiaApp" , newApp . Name ( ) )
2018-11-26 04:21:23 -08:00
var genesisState GenesisState
err = app . cdc . UnmarshalJSON ( appState , & genesisState )
if err != nil {
panic ( err )
2018-11-08 16:28:28 -08:00
}
2018-11-26 04:21:23 -08:00
ctxB := newApp . NewContext ( true , abci . Header { } )
newApp . initFromGenesisState ( ctxB , genesisState )
2018-11-08 16:28:28 -08:00
fmt . Printf ( "Comparing stores...\n" )
ctxA := app . NewContext ( true , abci . Header { } )
type StoreKeysPrefixes struct {
A sdk . StoreKey
B sdk . StoreKey
Prefixes [ ] [ ] byte
}
storeKeysPrefixes := [ ] StoreKeysPrefixes {
{ app . keyMain , newApp . keyMain , [ ] [ ] byte { } } ,
{ app . keyAccount , newApp . keyAccount , [ ] [ ] byte { } } ,
{ app . keyStake , newApp . keyStake , [ ] [ ] byte { stake . UnbondingQueueKey , stake . RedelegationQueueKey , stake . ValidatorQueueKey } } , // ordering may change but it doesn't matter
{ app . keySlashing , newApp . keySlashing , [ ] [ ] byte { } } ,
{ app . keyMint , newApp . keyMint , [ ] [ ] byte { } } ,
{ app . keyDistr , newApp . keyDistr , [ ] [ ] byte { } } ,
{ app . keyFeeCollection , newApp . keyFeeCollection , [ ] [ ] byte { } } ,
{ app . keyParams , newApp . keyParams , [ ] [ ] byte { } } ,
{ app . keyGov , newApp . keyGov , [ ] [ ] byte { } } ,
}
for _ , storeKeysPrefix := range storeKeysPrefixes {
storeKeyA := storeKeysPrefix . A
storeKeyB := storeKeysPrefix . B
prefixes := storeKeysPrefix . Prefixes
storeA := ctxA . KVStore ( storeKeyA )
storeB := ctxB . KVStore ( storeKeyB )
kvA , kvB , count , equal := sdk . DiffKVStores ( storeA , storeB , prefixes )
fmt . Printf ( "Compared %d key/value pairs between %s and %s\n" , count , storeKeyA , storeKeyB )
require . True ( t , equal , "unequal stores: %s / %s:\nstore A %s (%X) => %s (%X)\nstore B %s (%X) => %s (%X)" ,
storeKeyA , storeKeyB , kvA . Key , kvA . Key , kvA . Value , kvA . Value , kvB . Key , kvB . Key , kvB . Value , kvB . Value )
}
}
2018-11-26 04:21:23 -08:00
func TestGaiaSimulationAfterImport ( t * testing . T ) {
if ! enabled {
t . Skip ( "Skipping Gaia simulation after import" )
}
// Setup Gaia application
var logger log . Logger
if verbose {
logger = log . TestingLogger ( )
} else {
logger = log . NewNopLogger ( )
}
dir , _ := ioutil . TempDir ( "" , "goleveldb-gaia-sim" )
db , _ := dbm . NewGoLevelDB ( "Simulation" , dir )
defer func ( ) {
db . Close ( )
os . RemoveAll ( dir )
} ( )
2018-11-27 00:14:22 -08:00
app := NewGaiaApp ( logger , db , nil , fauxMerkleModeOpt )
2018-11-26 04:21:23 -08:00
require . Equal ( t , "GaiaApp" , app . Name ( ) )
// Run randomized simulation
stopEarly , err := simulation . SimulateFromSeed (
t , app . BaseApp , appStateFn , seed ,
testAndRunTxs ( app ) ,
invariants ( app ) ,
numBlocks ,
blockSize ,
commit ,
)
if commit {
// for memdb:
// fmt.Println("Database Size", db.Stats()["database.size"])
fmt . Println ( "GoLevelDB Stats" )
fmt . Println ( db . Stats ( ) [ "leveldb.stats" ] )
fmt . Println ( "GoLevelDB cached block size" , db . Stats ( ) [ "leveldb.cachedblock" ] )
}
require . Nil ( t , err )
if stopEarly {
// we can't export or import a zero-validator genesis
fmt . Printf ( "We can't export or import a zero-validator genesis, exiting test...\n" )
return
}
fmt . Printf ( "Exporting genesis...\n" )
appState , _ , err := app . ExportAppStateAndValidators ( true )
if err != nil {
panic ( err )
}
fmt . Printf ( "Importing genesis...\n" )
newDir , _ := ioutil . TempDir ( "" , "goleveldb-gaia-sim-2" )
newDB , _ := dbm . NewGoLevelDB ( "Simulation-2" , dir )
defer func ( ) {
newDB . Close ( )
os . RemoveAll ( newDir )
} ( )
2018-11-27 00:14:22 -08:00
newApp := NewGaiaApp ( log . NewNopLogger ( ) , newDB , nil , fauxMerkleModeOpt )
2018-11-26 04:21:23 -08:00
require . Equal ( t , "GaiaApp" , newApp . Name ( ) )
newApp . InitChain ( abci . RequestInitChain {
AppStateBytes : appState ,
} )
// Run randomized simulation on imported app
_ , err = simulation . SimulateFromSeed (
t , newApp . BaseApp , appStateFn , seed ,
testAndRunTxs ( newApp ) ,
invariants ( newApp ) ,
numBlocks ,
blockSize ,
commit ,
)
require . Nil ( t , err )
}
2018-08-16 14:45:07 -07:00
// TODO: Make another test for the fuzzer itself, which just has noOp txs
// and doesn't depend on gaia
2018-08-16 08:36:15 -07:00
func TestAppStateDeterminism ( t * testing . T ) {
2018-08-17 07:19:33 -07:00
if ! enabled {
t . Skip ( "Skipping Gaia simulation" )
2018-08-16 08:36:15 -07:00
}
2018-08-17 07:19:33 -07:00
2018-09-03 19:13:08 -07:00
numSeeds := 3
2018-08-17 07:19:33 -07:00
numTimesToRunPerSeed := 5
appHashList := make ( [ ] json . RawMessage , numTimesToRunPerSeed )
for i := 0 ; i < numSeeds ; i ++ {
seed := rand . Int63 ( )
for j := 0 ; j < numTimesToRunPerSeed ; j ++ {
logger := log . NewNopLogger ( )
db := dbm . NewMemDB ( )
app := NewGaiaApp ( logger , db , nil )
// Run randomized simulation
simulation . SimulateFromSeed (
t , app . BaseApp , appStateFn , seed ,
testAndRunTxs ( app ) ,
[ ] simulation . Invariant { } ,
2018-09-03 19:13:08 -07:00
50 ,
100 ,
2018-09-12 21:53:55 -07:00
true ,
2018-08-17 07:19:33 -07:00
)
appHash := app . LastCommitID ( ) . Hash
appHashList [ j ] = appHash
}
for k := 1 ; k < numTimesToRunPerSeed ; k ++ {
2018-08-27 14:27:00 -07:00
require . Equal ( t , appHashList [ 0 ] , appHashList [ k ] , "appHash list: %v" , appHashList )
2018-08-17 07:19:33 -07:00
}
2018-08-16 08:36:15 -07:00
}
}