Jae/simulator improvements (#2900)

* Make simulator operations predetermined
* Use new dbm.ReverseIterator API
* Simulation speed improvements
* Pin exact revisions, not branches
* Rename 'MountStoresIAVL' to 'MountStores'
* Zero Power Block fees to community pool
This commit is contained in:
Jae Kwon 2018-11-27 00:14:22 -08:00 committed by GitHub
parent 2e0dfc31af
commit d1e76221d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 265 additions and 118 deletions

69
Gopkg.lock generated
View File

@ -35,11 +35,11 @@
[[projects]]
branch = "master"
digest = "1:c0decf632843204d2b8781de7b26e7038584e2dcccc7e2f401e88ae85b1df2b7"
digest = "1:093bf93a65962e8191e3e8cd8fc6c363f83d43caca9739c906531ba7210a9904"
name = "github.com/btcsuite/btcd"
packages = ["btcec"]
pruneopts = "UT"
revision = "67e573d211ace594f1366b4ce9d39726c4b19bd0"
revision = "3dcf298fed2d5fd65918dc560b3942b2aa0629e8"
[[projects]]
digest = "1:386de157f7d19259a7f9c81f26ce011223ce0f090353c1152ffdf730d7d10ac2"
@ -88,12 +88,12 @@
version = "v0.6.0"
[[projects]]
digest = "1:31a18dae27a29aa074515e43a443abfd2ba6deb6d69309d8d7ce789c45f34659"
digest = "1:4062bc6de62d73e2be342243cf138cf499b34d558876db8d9430e2149388a4d8"
name = "github.com/go-logfmt/logfmt"
packages = ["."]
pruneopts = "UT"
revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5"
version = "v0.3.0"
revision = "07c9b44f60d7ffdfb7d8efe1ad539965737836dc"
version = "v0.4.0"
[[projects]]
digest = "1:586ea76dbd0374d6fb649a91d70d652b7fe0ccffb8910a77468e7702e7901f3d"
@ -157,20 +157,21 @@
version = "v1.6.2"
[[projects]]
digest = "1:43dd08a10854b2056e615d1b1d22ac94559d822e1f8b6fcc92c1a1057e85188e"
digest = "1:7b5c6e2eeaa9ae5907c391a91c132abfd5c9e8a784a341b5625e750c67e6825d"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
version = "v1.4.0"
[[projects]]
digest = "1:ea40c24cdbacd054a6ae9de03e62c5f252479b96c716375aace5c120d68647c8"
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
@ -271,14 +272,16 @@
version = "v1.0.0"
[[projects]]
digest = "1:c1a04665f9613e082e1209cf288bf64f4068dcd6c87a64bf1c4ff006ad422ba0"
digest = "1:26663fafdea73a38075b07e8e9d82fc0056379d2be8bb4e13899e8fda7c7dd23"
name = "github.com/prometheus/client_golang"
packages = [
"prometheus",
"prometheus/internal",
"prometheus/promhttp",
]
pruneopts = "UT"
revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632"
revision = "abad2d1bd44235a26707c172eab6bca5bf2dbad3"
version = "v0.9.1"
[[projects]]
branch = "master"
@ -298,7 +301,7 @@
"model",
]
pruneopts = "UT"
revision = "0b1957f9d949dfa3084171a6ec5642b38055276a"
revision = "4724e9255275ce38f7179b2478abeae4e28c904f"
[[projects]]
branch = "master"
@ -328,6 +331,14 @@
pruneopts = "UT"
revision = "e2704e165165ec55d062f5919b4b29494e9fa790"
[[projects]]
digest = "1:b0c25f00bad20d783d259af2af8666969e2fc343fa0dc9efe52936bbd67fb758"
name = "github.com/rs/cors"
packages = ["."]
pruneopts = "UT"
revision = "9a47f48565a795472d43519dd49aac781f3034fb"
version = "v1.6.0"
[[projects]]
digest = "1:6a4a11ba764a56d2758899ec6f3848d24698d48442ebce85ee7a3f63284526cd"
name = "github.com/spf13/afero"
@ -348,12 +359,12 @@
version = "v1.3.0"
[[projects]]
digest = "1:7ffc0983035bc7e297da3688d9fe19d60a420e9c38bef23f845c53788ed6a05e"
digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939"
name = "github.com/spf13/cobra"
packages = ["."]
pruneopts = "UT"
revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b"
version = "v0.0.1"
revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
version = "v0.0.3"
[[projects]]
digest = "1:68ea4e23713989dc20b1bded5d9da2c5f9be14ff9885beef481848edd18c26cb"
@ -372,12 +383,12 @@
version = "v1.0.3"
[[projects]]
digest = "1:f8e1a678a2571e265f4bf91a3e5e32aa6b1474a55cb0ea849750cc177b664d96"
digest = "1:ba07ec7953d565ac57a11b123a3bf0c8e848f2c7f637fccb0f9ce4f9e489d69a"
name = "github.com/spf13/viper"
packages = ["."]
pruneopts = "UT"
revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7"
version = "v1.0.0"
revision = "a1b837276271029e31f796ae5d03ba9ffb017244"
version = "v1.0.3"
[[projects]]
digest = "1:7e8d267900c7fa7f35129a2a37596e38ed0f11ca746d6d9ba727980ee138f9f6"
@ -426,15 +437,16 @@
version = "v0.14.1"
[[projects]]
digest = "1:9f8c4c93658315a795ffd3e0c943d39f78067dd8382b8d7bcfaf6686b92f3978"
branch = "jae/reverseiterator"
digest = "1:c42b83333367f9c701d2373c2ce11177382c41bfce3b105aa632eaf0e5654ccb"
name = "github.com/tendermint/iavl"
packages = ["."]
pruneopts = "UT"
revision = "fa74114f764f9827c4ad5573f990ed25bf8c4bac"
version = "v0.11.1"
revision = "d8d0eef715649bcc21682990ac635566119f070c"
[[projects]]
digest = "1:ba2ba7d6a0853472bdb7a64c4f9c1d5f9cba0eb7aac0b024654104387bf5eb57"
branch = "jae/reverseiterator"
digest = "1:db22ebc8142359cc3f8b6fc3954177be59358699af699794302cf60168dcf343"
name = "github.com/tendermint/tendermint"
packages = [
"abci/client",
@ -465,7 +477,6 @@
"libs/clist",
"libs/common",
"libs/db",
"libs/errors",
"libs/events",
"libs/fail",
"libs/flowrate",
@ -500,8 +511,7 @@
"version",
]
pruneopts = "UT"
revision = "80d0a362500fea2dd089258319075a54e5d40a2d"
version = "v0.26.1"
revision = "70a7cae58c8f880aede3b19101e54fb9a7b08c0b"
[[projects]]
digest = "1:7886f86064faff6f8d08a3eb0e8c773648ff5a2e27730831e2bfbf07467f6666"
@ -594,7 +604,7 @@
revision = "383e8b2c3b9e36c4076b235b32537292176bae20"
[[projects]]
digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74"
digest = "1:c3ad9841823db6da420a5625b367913b4ff54bbe60e8e3c98bd20e243e62e2d2"
name = "google.golang.org/grpc"
packages = [
".",
@ -610,7 +620,9 @@
"internal",
"internal/backoff",
"internal/channelz",
"internal/envconfig",
"internal/grpcrand",
"internal/transport",
"keepalive",
"metadata",
"naming",
@ -621,11 +633,10 @@
"stats",
"status",
"tap",
"transport",
]
pruneopts = "UT"
revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8"
version = "v1.13.0"
revision = "2e463a05d100327ca47ac218281906921038fd95"
version = "v1.16.0"
[[projects]]
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"

View File

@ -32,11 +32,11 @@
[[override]]
name = "github.com/tendermint/iavl"
version = "=v0.11.1"
revision = "d8d0eef715649bcc21682990ac635566119f070c"
[[override]]
name = "github.com/tendermint/tendermint"
version = "v0.26.1"
revision = "70a7cae58c8f880aede3b19101e54fb9a7b08c0b"
## deps without releases:

View File

@ -174,7 +174,7 @@ test_sim_gaia_nondeterminism:
test_sim_gaia_fast:
@echo "Running quick Gaia simulation. This may take several minutes..."
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=500 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=10 -v -timeout 24h
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=500 -SimulationBlockSize=200 -SimulationCommit=true -SimulationSeed=99 -v -timeout 24h
test_sim_gaia_import_export:
@echo "Running Gaia import/export simulation. This may take several minutes..."

View File

@ -56,6 +56,7 @@ type BaseApp struct {
endBlocker sdk.EndBlocker // logic to run after all txs, and to determine valset changes
addrPeerFilter sdk.PeerFilter // filter peers by address and port
pubkeyPeerFilter sdk.PeerFilter // filter peers by public key
fauxMerkleMode bool // if true, IAVL MountStores uses MountStoresDB for simulation speed.
//--------------------
// Volatile
@ -86,13 +87,14 @@ var _ abci.Application = (*BaseApp)(nil)
// Accepts variable number of option functions, which act on the BaseApp to set configuration choices
func NewBaseApp(name string, logger log.Logger, db dbm.DB, txDecoder sdk.TxDecoder, options ...func(*BaseApp)) *BaseApp {
app := &BaseApp{
Logger: logger,
name: name,
db: db,
cms: store.NewCommitMultiStore(db),
router: NewRouter(),
queryRouter: NewQueryRouter(),
txDecoder: txDecoder,
Logger: logger,
name: name,
db: db,
cms: store.NewCommitMultiStore(db),
router: NewRouter(),
queryRouter: NewQueryRouter(),
txDecoder: txDecoder,
fauxMerkleMode: false,
}
for _, option := range options {
option(app)
@ -111,10 +113,16 @@ func (app *BaseApp) SetCommitMultiStoreTracer(w io.Writer) {
app.cms.WithTracer(w)
}
// Mount IAVL stores to the provided keys in the BaseApp multistore
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
// Mount IAVL or DB stores to the provided keys in the BaseApp multistore
func (app *BaseApp) MountStores(keys ...*sdk.KVStoreKey) {
for _, key := range keys {
app.MountStore(key, sdk.StoreTypeIAVL)
if !app.fauxMerkleMode {
app.MountStore(key, sdk.StoreTypeIAVL)
} else {
// StoreTypeDB doesn't do anything upon commit, and it doesn't
// retain history, but it's useful for faster simulation.
app.MountStore(key, sdk.StoreTypeDB)
}
}
}

View File

@ -60,7 +60,7 @@ func setupBaseApp(t *testing.T, options ...func(*BaseApp)) *BaseApp {
app.LoadLatestVersion(capKey1)
})
app.MountStoresIAVL(capKey1, capKey2)
app.MountStores(capKey1, capKey2)
// stores are mounted
err := app.LoadLatestVersion(capKey1)
@ -91,7 +91,7 @@ func TestLoadVersion(t *testing.T) {
// make a cap key and mount the store
capKey := sdk.NewKVStoreKey("main")
app.MountStoresIAVL(capKey)
app.MountStores(capKey)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
require.Nil(t, err)
@ -117,7 +117,7 @@ func TestLoadVersion(t *testing.T) {
// reload with LoadLatestVersion
app = NewBaseApp(name, logger, db, nil)
app.MountStoresIAVL(capKey)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(2), commitID2)
@ -125,7 +125,7 @@ func TestLoadVersion(t *testing.T) {
// reload with LoadVersion, see if you can commit the same block and get
// the same result
app = NewBaseApp(name, logger, db, nil)
app.MountStoresIAVL(capKey)
app.MountStores(capKey)
err = app.LoadVersion(1, capKey)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(1), commitID1)
@ -161,7 +161,7 @@ func testChangeNameHelper(name string) func(*BaseApp) {
// make a cap key and mount the store
capKey := sdk.NewKVStoreKey("main")
app.MountStoresIAVL(capKey)
app.MountStores(capKey)
err := app.LoadLatestVersion(capKey) // needed to make stores non-nil
require.Nil(t, err)
@ -219,7 +219,7 @@ func TestInitChainer(t *testing.T) {
app := NewBaseApp(name, logger, db, nil)
capKey := sdk.NewKVStoreKey("main")
capKey2 := sdk.NewKVStoreKey("key2")
app.MountStoresIAVL(capKey, capKey2)
app.MountStores(capKey, capKey2)
// set a value in the store on init chain
key, value := []byte("hello"), []byte("goodbye")
@ -262,7 +262,7 @@ func TestInitChainer(t *testing.T) {
// reload app
app = NewBaseApp(name, logger, db, nil)
app.SetInitChainer(initChainer)
app.MountStoresIAVL(capKey, capKey2)
app.MountStores(capKey, capKey2)
err = app.LoadLatestVersion(capKey) // needed to make stores non-nil
require.Nil(t, err)

View File

@ -102,6 +102,16 @@ func (app *BaseApp) SetPubKeyPeerFilter(pf sdk.PeerFilter) {
app.pubkeyPeerFilter = pf
}
func (app *BaseApp) SetFauxMerkleMode() {
if app.sealed {
panic("SetFauxMerkleMode() on sealed BaseApp")
}
app.fauxMerkleMode = true
}
//----------------------------------------
// TODO: move these out of this file?
func (app *BaseApp) Router() Router {
if app.sealed {
panic("Router() on sealed BaseApp")

View File

@ -18,7 +18,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/log"
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
rpcserver "github.com/tendermint/tendermint/rpc/lib/server"
// Import statik for light client stuff
_ "github.com/cosmos/cosmos-sdk/client/lcd/statik"
@ -87,9 +87,9 @@ func (rs *RestServer) Start(listenAddr string, sslHosts string,
"Insecure mode is temporarily disabled, please locally generate an " +
"SSL certificate to test. Support will be re-enabled soon!",
)
// listener, err = tmserver.StartHTTPServer(
// listener, err = rpcserver.StartHTTPServer(
// listenAddr, handler, logger,
// tmserver.Config{MaxOpenConnections: maxOpen},
// rpcserver.Config{MaxOpenConnections: maxOpen},
// )
// if err != nil {
// return
@ -120,16 +120,19 @@ func (rs *RestServer) Start(listenAddr string, sslHosts string,
}()
}
rs.listener, err = tmserver.StartHTTPAndTLSServer(
listenAddr, rs.Mux,
certFile, keyFile,
rs.log,
tmserver.Config{MaxOpenConnections: maxOpen},
rs.listener, err = rpcserver.Listen(
listenAddr,
rpcserver.Config{MaxOpenConnections: maxOpen},
)
if err != nil {
return
}
go rpcserver.StartHTTPAndTLSServer(
rs.listener,
rs.Mux,
certFile, keyFile,
rs.log,
)
rs.log.Info(rs.fingerprint)
rs.log.Info("REST server started")
}

View File

@ -360,13 +360,16 @@ func startTM(
}
// startLCD starts the LCD.
//
// NOTE: This causes the thread to block.
func startLCD(logger log.Logger, listenAddr string, cdc *codec.Codec, t *testing.T) (net.Listener, error) {
rs := NewRestServer(cdc)
rs.setKeybase(GetTestKeyBase(t))
registerRoutes(rs)
return tmrpc.StartHTTPServer(listenAddr, rs.Mux, logger, tmrpc.Config{})
listener, err := tmrpc.Listen(listenAddr, tmrpc.Config{})
if err != nil {
return nil, err
}
go tmrpc.StartHTTPServer(listener, rs.Mux, logger)
return listener, nil
}
// NOTE: If making updates here also update cmd/gaia/cmd/gaiacli/main.go

View File

@ -156,7 +156,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
AddRoute("stake", stake.NewQuerier(app.stakeKeeper, app.cdc))
// initialize BaseApp
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keyMint, app.keyDistr,
app.MountStores(app.keyMain, app.keyAccount, app.keyStake, app.keyMint, app.keyDistr,
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
app.SetInitChainer(app.initChainer)
app.SetBeginBlocker(app.BeginBlocker)
@ -188,7 +188,6 @@ func MakeCodec() *codec.Codec {
// application updates every end block
func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
// distribute rewards from previous block
distr.BeginBlocker(ctx, req, app.distrKeeper)
@ -196,6 +195,13 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
// mint new tokens for this new block
mint.BeginBlocker(ctx, app.mintKeeper)
// slash anyone who double signed.
// NOTE: This should happen after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool,
// so as to keep the CanWithdrawInvariant invariant.
// TODO: This should really happen at EndBlocker.
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
return abci.ResponseBeginBlock{
Tags: tags.ToKVPairs(),
}

View File

@ -16,6 +16,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"
authsim "github.com/cosmos/cosmos-sdk/x/auth/simulation"
banksim "github.com/cosmos/cosmos-sdk/x/bank/simulation"
@ -193,6 +194,11 @@ func invariants(app *GaiaApp) []simulation.Invariant {
}
}
// Pass this in as an option to use a dbStoreAdapter instead of an IAVLStore for simulation speed.
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
bapp.SetFauxMerkleMode()
}
// Profile with:
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -SimulationCommit=true -cpuprofile cpu.out
func BenchmarkFullGaiaSimulation(b *testing.B) {
@ -249,7 +255,7 @@ func TestFullGaiaSimulation(t *testing.T) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil)
app := NewGaiaApp(logger, db, nil, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", app.Name())
// Run randomized simulation
@ -291,7 +297,7 @@ func TestGaiaImportExport(t *testing.T) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil)
app := NewGaiaApp(logger, db, nil, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", app.Name())
// Run randomized simulation
@ -328,7 +334,7 @@ func TestGaiaImportExport(t *testing.T) {
newDB.Close()
os.RemoveAll(newDir)
}()
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil)
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", newApp.Name())
var genesisState GenesisState
err = app.cdc.UnmarshalJSON(appState, &genesisState)
@ -388,7 +394,7 @@ func TestGaiaSimulationAfterImport(t *testing.T) {
db.Close()
os.RemoveAll(dir)
}()
app := NewGaiaApp(logger, db, nil)
app := NewGaiaApp(logger, db, nil, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", app.Name())
// Run randomized simulation
@ -431,7 +437,7 @@ func TestGaiaSimulationAfterImport(t *testing.T) {
newDB.Close()
os.RemoveAll(newDir)
}()
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil)
newApp := NewGaiaApp(log.NewNopLogger(), newDB, nil, fauxMerkleModeOpt)
require.Equal(t, "GaiaApp", newApp.Name())
newApp.InitChain(abci.RequestInitChain{
AppStateBytes: appState,

View File

@ -188,7 +188,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyStake, app.keySlashing, app.keyParams)
app.MountStores(app.keyMain, app.keyAccount, app.keyStake, app.keySlashing, app.keyParams)
app.MountStore(app.tkeyParams, sdk.StoreTypeTransient)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {

View File

@ -89,7 +89,7 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.Ba
app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper))
// mount the multistore and load the latest state
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC)
app.MountStores(app.keyMain, app.keyAccount, app.keyIBC)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())

View File

@ -97,7 +97,7 @@ func NewDemocoinApp(logger log.Logger, db dbm.DB) *DemocoinApp {
// Initialize BaseApp.
app.SetInitChainer(app.initChainerFn(app.coolKeeper, app.powKeeper))
app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyPowStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.MountStores(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyPowStore, app.capKeyIBCStore, app.capKeyStakingStore)
app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper))
err := app.LoadLatestVersion(app.capKeyMainStore)
if err != nil {

View File

@ -35,7 +35,7 @@ func main() {
var baseApp = bam.NewBaseApp("kvstore", logger, db, decodeTx)
// Set mounts for BaseApp's MultiStore.
baseApp.MountStoresIAVL(capKeyMainStore)
baseApp.MountStores(capKeyMainStore)
// Set a handler Route.
baseApp.Router().AddRoute("kvstore", Handler(capKeyMainStore))

View File

@ -31,7 +31,7 @@ func NewApp(rootDir string, logger log.Logger) (abci.Application, error) {
baseApp := bam.NewBaseApp("kvstore", logger, db, decodeTx)
// Set mounts for BaseApp's MultiStore.
baseApp.MountStoresIAVL(capKeyMainStore)
baseApp.MountStores(capKeyMainStore)
baseApp.SetInitChainer(InitChainer(capKeyMainStore))

View File

@ -7,6 +7,7 @@ import (
"sync"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
)
// If value is nil but deleted is false, it means the parent doesn't have the
@ -159,29 +160,29 @@ func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator {
parent = ci.parent.ReverseIterator(start, end)
}
items := ci.dirtyItems(ascending)
items := ci.dirtyItems(start, end, ascending)
cache = newMemIterator(start, end, items)
return newCacheMergeIterator(parent, cache, ascending)
}
// Constructs a slice of dirty items, to use w/ memIterator.
func (ci *cacheKVStore) dirtyItems(ascending bool) []cmn.KVPair {
items := make([]cmn.KVPair, 0, len(ci.cache))
func (ci *cacheKVStore) dirtyItems(start, end []byte, ascending bool) []cmn.KVPair {
items := make([]cmn.KVPair, 0)
for key, cacheValue := range ci.cache {
if !cacheValue.dirty {
continue
}
items = append(items, cmn.KVPair{Key: []byte(key), Value: cacheValue.value})
if dbm.IsKeyInDomain([]byte(key), start, end) {
items = append(items, cmn.KVPair{Key: []byte(key), Value: cacheValue.value})
}
}
sort.Slice(items, func(i, j int) bool {
if ascending {
return bytes.Compare(items[i].Key, items[j].Key) < 0
}
return bytes.Compare(items[i].Key, items[j].Key) > 0
})

View File

@ -39,3 +39,28 @@ func (dsa dbStoreAdapter) Gas(meter GasMeter, config GasConfig) KVStore {
// dbm.DB implements KVStore so we can CacheKVStore it.
var _ KVStore = dbStoreAdapter{}
//----------------------------------------
// commitDBStoreWrapper should only be used for simulation/debugging,
// as it doesn't compute any commit hash, and it cannot load older state.
// Wrapper type for dbm.Db with implementation of KVStore
type commitDBStoreAdapter struct {
dbStoreAdapter
}
func (cdsa commitDBStoreAdapter) Commit() CommitID {
return CommitID{
Version: -1,
Hash: []byte("FAKE_HASH"),
}
}
func (cdsa commitDBStoreAdapter) LastCommitID() CommitID {
return CommitID{
Version: -1,
Hash: []byte("FAKE_HASH"),
}
}
func (cdsa commitDBStoreAdapter) SetPruning(_ PruningStrategy) {}

View File

@ -3,6 +3,7 @@ package store
import (
"testing"
"github.com/tendermint/iavl"
dbm "github.com/tendermint/tendermint/libs/db"
sdk "github.com/cosmos/cosmos-sdk/types"
@ -86,7 +87,7 @@ func testGasKVStoreWrap(t *testing.T, store KVStore) {
func TestGasKVStoreWrap(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
tree := iavl.NewMutableTree(db, cacheSize)
iavl := newIAVLStore(tree, numRecent, storeEvery)
testGasKVStoreWrap(t, iavl)

View File

@ -28,8 +28,8 @@ var (
nMoreData = 0
)
// make a tree and save it
func newTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, CommitID) {
// make a tree with data from above and save it
func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, CommitID) {
tree := iavl.NewMutableTree(db, cacheSize)
for k, v := range treeData {
tree.Set([]byte(k), []byte(v))
@ -46,7 +46,7 @@ func newTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, CommitID) {
func TestIAVLStoreGetSetHasDelete(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
tree, _ := newAlohaTree(t, db)
iavlStore := newIAVLStore(tree, numRecent, storeEvery)
key := "hello"
@ -71,7 +71,7 @@ func TestIAVLStoreGetSetHasDelete(t *testing.T) {
func TestIAVLIterator(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
tree, _ := newAlohaTree(t, db)
iavlStore := newIAVLStore(tree, numRecent, storeEvery)
iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz"))
expected := []string{"aloha", "hello"}
@ -142,9 +142,40 @@ func TestIAVLIterator(t *testing.T) {
require.Equal(t, len(expected), i)
}
func TestIAVLSubspaceIterator(t *testing.T) {
func TestIAVLReverseIterator(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
tree := iavl.NewMutableTree(db, cacheSize)
iavlStore := newIAVLStore(tree, numRecent, storeEvery)
iavlStore.Set([]byte{0x00}, []byte("0"))
iavlStore.Set([]byte{0x00, 0x00}, []byte("0 0"))
iavlStore.Set([]byte{0x00, 0x01}, []byte("0 1"))
iavlStore.Set([]byte{0x00, 0x02}, []byte("0 2"))
iavlStore.Set([]byte{0x01}, []byte("1"))
var testReverseIterator = func(t *testing.T, start []byte, end []byte, expected []string) {
iter := iavlStore.ReverseIterator(start, end)
var i int
for i = 0; iter.Valid(); iter.Next() {
expectedValue := expected[i]
value := iter.Value()
require.EqualValues(t, string(value), expectedValue)
i++
}
require.Equal(t, len(expected), i)
}
testReverseIterator(t, nil, nil, []string{"1", "0 2", "0 1", "0 0", "0"})
testReverseIterator(t, []byte{0x00}, nil, []string{"1", "0 2", "0 1", "0 0", "0"})
testReverseIterator(t, []byte{0x00}, []byte{0x00, 0x01}, []string{"0 0", "0"})
testReverseIterator(t, []byte{0x00}, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"})
testReverseIterator(t, []byte{0x00, 0x01}, []byte{0x01}, []string{"0 2", "0 1"})
testReverseIterator(t, nil, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"})
}
func TestIAVLPrefixIterator(t *testing.T) {
db := dbm.NewMemDB()
tree := iavl.NewMutableTree(db, cacheSize)
iavlStore := newIAVLStore(tree, numRecent, storeEvery)
iavlStore.Set([]byte("test1"), []byte("test1"))
@ -204,9 +235,9 @@ func TestIAVLSubspaceIterator(t *testing.T) {
require.Equal(t, len(expected), i)
}
func TestIAVLReverseSubspaceIterator(t *testing.T) {
func TestIAVLReversePrefixIterator(t *testing.T) {
db := dbm.NewMemDB()
tree, _ := newTree(t, db)
tree := iavl.NewMutableTree(db, cacheSize)
iavlStore := newIAVLStore(tree, numRecent, storeEvery)
iavlStore.Set([]byte("test1"), []byte("test1"))

View File

@ -18,8 +18,7 @@ type memIterator struct {
func newMemIterator(start, end []byte, items []cmn.KVPair) *memIterator {
itemsInDomain := make([]cmn.KVPair, 0)
for _, item := range items {
ascending := keyCompare(start, end) < 0
if dbm.IsKeyInDomain(item.Key, start, end, !ascending) {
if dbm.IsKeyInDomain(item.Key, start, end) {
itemsInDomain = append(itemsInDomain, item)
}
}

View File

@ -99,24 +99,16 @@ func (s prefixStore) Iterator(start, end []byte) Iterator {
// Implements KVStore
// Check https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db.go#L129
func (s prefixStore) ReverseIterator(start, end []byte) Iterator {
var newstart []byte
if start == nil {
newstart = cpIncr(s.prefix)
} else {
newstart = cloneAppend(s.prefix, start)
}
newstart := cloneAppend(s.prefix, start)
var newend []byte
if end == nil {
newend = cpDecr(s.prefix)
newend = cpIncr(s.prefix)
} else {
newend = cloneAppend(s.prefix, end)
}
iter := s.parent.ReverseIterator(newstart, newend)
if start == nil {
skipOne(iter, cpIncr(s.prefix))
}
return newPrefixIterator(s.prefix, start, end, iter)
}

View File

@ -388,13 +388,15 @@ func TestPrefixDBReverseIterator2(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.ReverseIterator(nil, bz(""))
checkDomain(t, itr, nil, bz(""))
itr := pstore.ReverseIterator(bz(""), nil)
checkDomain(t, itr, bz(""), nil)
checkItem(t, itr, bz("3"), bz("value3"))
checkNext(t, itr, true)
checkItem(t, itr, bz("2"), bz("value2"))
checkNext(t, itr, true)
checkItem(t, itr, bz("1"), bz("value1"))
checkNext(t, itr, true)
checkItem(t, itr, bz(""), bz("value"))
checkNext(t, itr, false)
checkInvalid(t, itr)
itr.Close()
@ -404,10 +406,8 @@ func TestPrefixDBReverseIterator3(t *testing.T) {
store := mockStoreWithStuff()
pstore := store.Prefix(bz("key"))
itr := pstore.ReverseIterator(bz(""), nil)
checkDomain(t, itr, bz(""), nil)
checkItem(t, itr, bz(""), bz("value"))
checkNext(t, itr, false)
itr := pstore.ReverseIterator(nil, bz(""))
checkDomain(t, itr, nil, bz(""))
checkInvalid(t, itr)
itr.Close()
}

View File

@ -358,7 +358,8 @@ func (rs *rootMultiStore) loadCommitStoreFromParams(key sdk.StoreKey, id CommitI
store, err = LoadIAVLStore(db, id, rs.pruning)
return
case sdk.StoreTypeDB:
panic("dbm.DB is not a CommitStore")
store = commitDBStoreAdapter{dbStoreAdapter{db}}
return
case sdk.StoreTypeTransient:
_, ok := key.(*sdk.TransientStoreKey)
if !ok {

View File

@ -143,7 +143,7 @@ type KVStore interface {
Iterator(start, end []byte) Iterator
// Iterator over a domain of keys in descending order. End is exclusive.
// Start must be greater than end, or the Iterator is invalid.
// Start must be less than end, or the Iterator is invalid.
// Iterator must be closed by caller.
// CONTRACT: No writes may happen within a domain while an iterator exists over it.
ReverseIterator(start, end []byte) Iterator

View File

@ -16,6 +16,8 @@ type (
ValidatorDistInfo = types.ValidatorDistInfo
TotalAccum = types.TotalAccum
FeePool = types.FeePool
DecCoin = types.DecCoin
DecCoins = types.DecCoins
MsgSetWithdrawAddress = types.MsgSetWithdrawAddress
MsgWithdrawDelegatorRewardsAll = types.MsgWithdrawDelegatorRewardsAll
@ -56,6 +58,8 @@ var (
NewMsgWithdrawDelegatorRewardsAll = types.NewMsgWithdrawDelegatorRewardsAll
NewMsgWithdrawDelegatorReward = types.NewMsgWithdrawDelegatorReward
NewMsgWithdrawValidatorRewardsAll = types.NewMsgWithdrawValidatorRewardsAll
NewDecCoins = types.NewDecCoins
)
const (

View File

@ -18,6 +18,16 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, percentVotes sdk.Dec, proposer s
feesCollected := k.feeCollectionKeeper.GetCollectedFees(ctx)
feesCollectedDec := types.NewDecCoins(feesCollected)
feePool := k.GetFeePool(ctx)
// Temporary workaround to keep CanWithdrawInvariant happy.
// General discussions here: https://github.com/cosmos/cosmos-sdk/issues/2906#issuecomment-441867634
if k.stakeKeeper.GetLastTotalPower(ctx).IsZero() {
feePool.CommunityPool = feePool.CommunityPool.Plus(feesCollectedDec)
k.SetFeePool(ctx, feePool)
k.feeCollectionKeeper.ClearCollectedFees(ctx)
return
}
// allocated rewards to proposer
baseProposerReward := k.GetBaseProposerReward(ctx)
bonusProposerReward := k.GetBonusProposerReward(ctx)
@ -33,7 +43,6 @@ func (k Keeper) AllocateTokens(ctx sdk.Context, percentVotes sdk.Dec, proposer s
// allocate community funding
communityTax := k.GetCommunityTax(ctx)
communityFunding := feesCollectedDec.MulDec(communityTax)
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Plus(communityFunding)
// set the global pool within the distribution module

View File

@ -102,10 +102,6 @@ func (k Keeper) WithdrawValidatorRewardsAll(ctx sdk.Context, operatorAddr sdk.Va
accAddr := sdk.AccAddress(operatorAddr.Bytes())
withdraw := k.withdrawDelegationRewardsAll(ctx, accAddr)
//if withdraw.AmountOf {
//return types.ErrNoValidatorDistInfo(k.codespace)
//}
// withdrawal validator commission rewards
valInfo := k.GetValidatorDistInfo(ctx, operatorAddr)
wc := k.GetWithdrawContext(ctx, operatorAddr)

View File

@ -179,6 +179,5 @@ func CanWithdrawInvariant(k distr.Keeper, sk stake.Keeper) simulation.Invariant
// all ok
return nil
}
}

View File

@ -184,7 +184,7 @@ func (coins DecCoins) AmountOf(denom string) sdk.Dec {
}
}
// returns the amount of a denom from deccoins
// has a negative DecCoin amount
func (coins DecCoins) HasNegative() bool {
for _, coin := range coins {
if coin.Amount.IsNegative() {

View File

@ -91,7 +91,7 @@ func (vi ValidatorDistInfo) TakeFeePoolRewards(wc WithdrawContext) (
if accum.GT(fp.TotalValAccum.Accum) {
panic("individual accum should never be greater than the total")
}
withdrawalTokens := fp.ValPool.MulDec(accum).QuoDec(fp.TotalValAccum.Accum)
withdrawalTokens := fp.ValPool.MulDec(accum).QuoDec(fp.TotalValAccum.Accum) // XXX ensure this doesn't cause problems
remValPool := fp.ValPool.Minus(withdrawalTokens)
commission := withdrawalTokens.MulDec(wc.CommissionRate)

View File

@ -192,7 +192,7 @@ func randomProposalID(r *rand.Rand, k gov.Keeper, ctx sdk.Context) (proposalID u
if lastProposalID < 1 {
return 0, false
}
proposalID = uint64(r.Intn(int(lastProposalID)))
proposalID = uint64(r.Intn(1+int(lastProposalID)) - 1)
return proposalID, true
}

View File

@ -62,3 +62,29 @@ func RandTimestamp(r *rand.Rand) time.Time {
unixTime := r.Int63n(253373529600)
return time.Unix(unixTime, 0)
}
// Derive a new rand deterministically from a rand.
// Unlike rand.New(rand.NewSource(seed)), the result is "more random"
// depending on the source and state of r.
// NOTE: not crypto safe.
func DeriveRand(r *rand.Rand) *rand.Rand {
const num = 8 // TODO what's a good number? Too large is too slow.
ms := multiSource(make([]rand.Source, num))
for i := 0; i < num; i++ {
ms[i] = rand.NewSource(r.Int63())
}
return rand.New(ms)
}
type multiSource []rand.Source
func (ms multiSource) Int63() (r int64) {
for _, source := range ms {
r ^= source.Int63()
}
return r
}
func (ms multiSource) Seed(seed int64) {
panic("multiSource Seed should not be called")
}

View File

@ -249,9 +249,25 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, params
header.Height, totalNumBlocks, opCount, blocksize)
lastBlocksizeState, blocksize = getBlockSize(r, params, lastBlocksizeState, avgBlockSize)
type opAndR struct {
op Operation
rand *rand.Rand
}
opAndRz := make([]opAndR, 0, blocksize)
// Predetermine the blocksize slice so that we can do things like block
// out certain operations without changing the ops that follow.
for i := 0; i < blocksize; i++ {
opAndRz = append(opAndRz, opAndR{
op: selectOp(r),
rand: DeriveRand(r),
})
}
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event)
for i := 0; i < blocksize; i++ {
// NOTE: the Rand 'r' should not be used here.
opAndR := opAndRz[i]
op, r2 := opAndR.op, opAndR.rand
logUpdate, futureOps, err := op(r2, app, ctx, accounts, event)
logWriter(logUpdate)
if err != nil {
displayLogs()