Merge PR #2310: staking transient store for Tendermint Updates

* working

* non-tests compile

* fix mounting error, working on testing

* stumped using transient store

* joon comments

* remove old comments

* resolve ibc error

* lint/sim_test

* fix determinism sim test

* sim enable commit

* docs and pending
This commit is contained in:
Rigel 2018-09-13 00:53:55 -04:00 committed by GitHub
parent 8682556fad
commit 5bf9401e87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 134 additions and 129 deletions

View File

@ -157,11 +157,11 @@ 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=400 -SimulationBlockSize=200 -v -timeout 24h
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=400 -SimulationBlockSize=200 -SimulationCommit=true -v -timeout 24h
test_sim_gaia_slow:
@echo "Running full Gaia simulation. This may take awhile!"
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -v -timeout 24h
@go test ./cmd/gaia/app -run TestFullGaiaSimulation -SimulationEnabled=true -SimulationNumBlocks=1000 -SimulationVerbose=true -SimulationCommit=true -v -timeout 24h
SIM_NUM_BLOCKS ?= 210
SIM_BLOCK_SIZE ?= 200

View File

@ -33,6 +33,7 @@ BREAKING CHANGES
renamed for accounts and validator operators:
* `cosmosaccaddr` / `cosmosaccpub` => `cosmos` / `cosmospub`
* `cosmosvaladdr` / `cosmosvalpub` => `cosmosvaloper` / `cosmosvaloperpub`
* [x/stake] [#1013] TendermintUpdates now uses transient store
* SDK
* [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal

View File

@ -120,13 +120,20 @@ func (app *BaseApp) RegisterCodespace(codespace sdk.CodespaceType) sdk.Codespace
return app.codespacer.RegisterNext(codespace)
}
// Mount a store to the provided key in the BaseApp multistore
// Mount IAVL stores to the provided keys in the BaseApp multistore
func (app *BaseApp) MountStoresIAVL(keys ...*sdk.KVStoreKey) {
for _, key := range keys {
app.MountStore(key, sdk.StoreTypeIAVL)
}
}
// Mount stores to the provided keys in the BaseApp multistore
func (app *BaseApp) MountStoresTransient(keys ...*sdk.TransientStoreKey) {
for _, key := range keys {
app.MountStore(key, sdk.StoreTypeTransient)
}
}
// Mount a store to the provided key in the BaseApp multistore, using a specified DB
func (app *BaseApp) MountStoreWithDB(key sdk.StoreKey, typ sdk.StoreType, db dbm.DB) {
app.cms.MountStoreWithDB(key, typ, db)

View File

@ -43,6 +43,7 @@ type GaiaApp struct {
keyAccount *sdk.KVStoreKey
keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey
tkeyStake *sdk.TransientStoreKey
keySlashing *sdk.KVStoreKey
keyGov *sdk.KVStoreKey
keyFeeCollection *sdk.KVStoreKey
@ -74,6 +75,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
keyAccount: sdk.NewKVStoreKey("acc"),
keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"),
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyGov: sdk.NewKVStoreKey("gov"),
keyFeeCollection: sdk.NewKVStoreKey("fee"),
@ -92,7 +94,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
app.stakeKeeper = app.stakeKeeper.WithValidatorHooks(app.slashingKeeper.ValidatorHooks())
app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper.Setter(), app.bankKeeper, app.stakeKeeper, app.RegisterCodespace(gov.DefaultCodespace))
@ -114,8 +116,9 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptio
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
app.MountStore(app.tkeyParams, sdk.StoreTypeTransient)
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake,
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
app.MountStoresTransient(app.tkeyParams, app.tkeyStake)
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())

View File

@ -209,9 +209,9 @@ func TestAppStateDeterminism(t *testing.T) {
[]simulation.Invariant{},
50,
100,
false,
true,
)
app.Commit()
//app.Commit()
appHash := app.LastCommitID().Hash
appHashList[j] = appHash
}

View File

@ -134,6 +134,7 @@ type GaiaApp struct {
keyAccount *sdk.KVStoreKey
keyIBC *sdk.KVStoreKey
keyStake *sdk.KVStoreKey
tkeyStake *sdk.TransientStoreKey
keySlashing *sdk.KVStoreKey
keyParams *sdk.KVStoreKey
@ -161,6 +162,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
keyAccount: sdk.NewKVStoreKey("acc"),
keyIBC: sdk.NewKVStoreKey("ibc"),
keyStake: sdk.NewKVStoreKey("stake"),
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
keySlashing: sdk.NewKVStoreKey("slashing"),
keyParams: sdk.NewKVStoreKey("params"),
}
@ -176,7 +178,7 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, baseAppOptions ...func(*bam.BaseAp
app.bankKeeper = bank.NewBaseKeeper(app.accountMapper)
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams)
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.tkeyStake, app.bankKeeper, app.RegisterCodespace(stake.DefaultCodespace))
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.paramsKeeper.Getter(), app.RegisterCodespace(slashing.DefaultCodespace))
// register message routes

View File

@ -55,7 +55,7 @@ func getMockApp(t *testing.T) *mock.App {
mapp.SetInitChainer(getInitChainer(mapp, keeper, "ice-cold"))
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyCool}))
require.NoError(t, mapp.CompleteSetup(keyCool))
return mapp
}

View File

@ -32,7 +32,7 @@ func getMockApp(t *testing.T) *mock.App {
mapp.SetInitChainer(getInitChainer(mapp, keeper))
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyPOW}))
require.NoError(t, mapp.CompleteSetup(keyPOW))
mapp.Seal()

View File

@ -19,7 +19,7 @@ func getBenchmarkMockApp() (*mock.App, error) {
bankKeeper := NewBaseKeeper(mapp.AccountMapper)
mapp.Router().AddRoute("bank", NewHandler(bankKeeper))
err := mapp.CompleteSetup([]*sdk.KVStoreKey{})
err := mapp.CompleteSetup()
return mapp, err
}

View File

@ -21,7 +21,7 @@ func TestBankWithRandomMessages(t *testing.T) {
bankKeeper := bank.NewBaseKeeper(mapper)
mapp.Router().AddRoute("bank", bank.NewHandler(bankKeeper))
err := mapp.CompleteSetup([]*sdk.KVStoreKey{})
err := mapp.CompleteSetup()
if err != nil {
panic(err)
}

View File

@ -115,7 +115,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
logger.Info(
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %s steak); deleted",
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %v steak (had only %v steak); deleted",
inactiveProposal.GetProposalID(),
inactiveProposal.GetTitle(),
keeper.GetDepositProcedure(ctx).MinDeposit.AmountOf("steak"),

View File

@ -26,7 +26,8 @@ func TestGovWithRandomMessages(t *testing.T) {
mapper := mapp.AccountMapper
bankKeeper := bank.NewBaseKeeper(mapper)
stakeKey := sdk.NewKVStoreKey("stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace)
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
paramKey := sdk.NewKVStoreKey("params")
paramKeeper := params.NewKeeper(mapp.Cdc, paramKey)
govKey := sdk.NewKVStoreKey("gov")
@ -37,7 +38,7 @@ func TestGovWithRandomMessages(t *testing.T) {
return abci.ResponseEndBlock{}
})
err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey, paramKey, govKey})
err := mapp.CompleteSetup(stakeKey, stakeTKey, paramKey, govKey)
if err != nil {
panic(err)
}

View File

@ -28,18 +28,19 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
keyGlobalParams := sdk.NewKVStoreKey("params")
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keyGov := sdk.NewKVStoreKey("gov")
pk := params.NewKeeper(mapp.Cdc, keyGlobalParams)
ck := bank.NewBaseKeeper(mapp.AccountMapper)
sk := stake.NewKeeper(mapp.Cdc, keyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace))
sk := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, ck, mapp.RegisterCodespace(stake.DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keyGov, pk.Setter(), ck, sk, DefaultCodespace)
mapp.Router().AddRoute("gov", NewHandler(keeper))
mapp.SetEndBlocker(getEndBlocker(keeper))
mapp.SetInitChainer(getInitChainer(mapp, keeper, sk))
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keyGov, keyGlobalParams}))
require.NoError(t, mapp.CompleteSetup(keyStake, keyGov, keyGlobalParams, tkeyStake))
genAccs, addrs, pubKeys, privKeys := mock.CreateGenAccounts(numGenAccs, sdk.Coins{sdk.NewInt64Coin("steak", 42)})

View File

@ -24,7 +24,7 @@ func getMockApp(t *testing.T) *mock.App {
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
mapp.Router().AddRoute("ibc", NewHandler(ibcMapper, bankKeeper))
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyIBC}))
require.NoError(t, mapp.CompleteSetup(keyIBC))
return mapp
}

View File

@ -1,6 +1,7 @@
package mock
import (
"fmt"
"math/rand"
"os"
@ -75,11 +76,21 @@ func NewApp() *App {
// CompleteSetup completes the application setup after the routes have been
// registered.
func (app *App) CompleteSetup(newKeys []*sdk.KVStoreKey) error {
func (app *App) CompleteSetup(newKeys ...sdk.StoreKey) error {
newKeys = append(newKeys, app.KeyMain)
newKeys = append(newKeys, app.KeyAccount)
app.MountStoresIAVL(newKeys...)
for _, key := range newKeys {
switch key.(type) {
case *sdk.KVStoreKey:
app.MountStore(key, sdk.StoreTypeIAVL)
case *sdk.TransientStoreKey:
app.MountStore(key, sdk.StoreTypeTransient)
default:
return fmt.Errorf("unsupported StoreKey: %+v", key)
}
}
err := app.LoadLatestVersion(app.KeyMain)
return err

View File

@ -41,7 +41,7 @@ func getMockApp(t *testing.T) *App {
mApp := NewApp()
mApp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return })
require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{}))
require.NoError(t, mApp.CompleteSetup())
return mApp
}

View File

@ -24,10 +24,11 @@ import (
)
// Simulate tests application by sending random messages.
func Simulate(
t *testing.T, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, ops []WeightedOperation, setups []RandSetup,
invariants []Invariant, numBlocks int, blockSize int, commit bool,
) error {
func Simulate(t *testing.T, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
ops []WeightedOperation, setups []RandSetup,
invariants []Invariant, numBlocks int, blockSize int, commit bool) error {
time := time.Now().UnixNano()
return SimulateFromSeed(t, app, appStateFn, time, ops, setups, invariants, numBlocks, blockSize, commit)
}
@ -54,10 +55,11 @@ func randTimestamp(r *rand.Rand) time.Time {
// SimulateFromSeed tests an application by running the provided
// operations, testing the provided invariants, but using the provided seed.
func SimulateFromSeed(
tb testing.TB, app *baseapp.BaseApp, appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage, seed int64, ops []WeightedOperation, setups []RandSetup,
invariants []Invariant, numBlocks int, blockSize int, commit bool,
) (simError error) {
func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
appStateFn func(r *rand.Rand, keys []crypto.PrivKey, accs []sdk.AccAddress) json.RawMessage,
seed int64, ops []WeightedOperation, setups []RandSetup, invariants []Invariant,
numBlocks int, blockSize int, commit bool) (simError error) {
// in case we have to end early, don't os.Exit so that we can run cleanup code.
stopEarly := false
testingMode, t, b := getTestingMode(tb)

View File

@ -26,11 +26,12 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
RegisterWire(mapp.Cdc)
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keySlashing := sdk.NewKVStoreKey("slashing")
keyParams := sdk.NewKVStoreKey("params")
bankKeeper := bank.NewBaseKeeper(mapp.AccountMapper)
paramsKeeper := params.NewKeeper(mapp.Cdc, keyParams)
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
stakeKeeper := stake.NewKeeper(mapp.Cdc, keyStake, tkeyStake, bankKeeper, mapp.RegisterCodespace(stake.DefaultCodespace))
keeper := NewKeeper(mapp.Cdc, keySlashing, stakeKeeper, paramsKeeper.Getter(), mapp.RegisterCodespace(DefaultCodespace))
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
@ -38,7 +39,7 @@ func getMockApp(t *testing.T) (*mock.App, stake.Keeper, Keeper) {
mapp.SetEndBlocker(getEndBlocker(stakeKeeper))
mapp.SetInitChainer(getInitChainer(mapp, stakeKeeper))
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{keyStake, keySlashing, keyParams}))
require.NoError(t, mapp.CompleteSetup(keyStake, keySlashing, keyParams, tkeyStake))
return mapp, stakeKeeper, keeper
}

View File

@ -52,11 +52,13 @@ func createTestCodec() *wire.Codec {
func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, params.Setter, Keeper) {
keyAcc := sdk.NewKVStoreKey("acc")
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keySlashing := sdk.NewKVStoreKey("slashing")
keyParams := sdk.NewKVStoreKey("params")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyParams, sdk.StoreTypeIAVL, db)
@ -67,7 +69,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para
accountMapper := auth.NewAccountMapper(cdc, keyAcc, auth.ProtoBaseAccount)
ck := bank.NewBaseKeeper(accountMapper)
params := params.NewKeeper(cdc, keyParams)
sk := stake.NewKeeper(cdc, keyStake, ck, stake.DefaultCodespace)
sk := stake.NewKeeper(cdc, keyStake, tkeyStake, ck, stake.DefaultCodespace)
genesis := stake.DefaultGenesisState()
genesis.Pool.LooseTokens = sdk.NewDec(initCoins.MulRaw(int64(len(addrs))).Int64())

View File

@ -34,14 +34,15 @@ func getMockApp(t *testing.T) (*mock.App, Keeper) {
RegisterWire(mApp.Cdc)
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
bankKeeper := bank.NewBaseKeeper(mApp.AccountMapper)
keeper := NewKeeper(mApp.Cdc, keyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace))
keeper := NewKeeper(mApp.Cdc, keyStake, tkeyStake, bankKeeper, mApp.RegisterCodespace(DefaultCodespace))
mApp.Router().AddRoute("stake", NewHandler(keeper))
mApp.SetEndBlocker(getEndBlocker(keeper))
mApp.SetInitChainer(getInitChainer(mApp, keeper))
require.NoError(t, mApp.CompleteSetup([]*sdk.KVStoreKey{keyStake}))
require.NoError(t, mApp.CompleteSetup(keyStake, tkeyStake))
return mApp, keeper
}

View File

@ -53,7 +53,6 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (ValidatorUpdates []abci.Valid
// calculate validator set changes
ValidatorUpdates = k.GetValidTendermintUpdates(ctx)
k.ClearTendermintUpdates(ctx)
return
}

View File

@ -3,6 +3,7 @@
This document provided a bit more insight as to the purpose of several related
prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
# IAVL Store
## Validators
- Prefix Key Space: ValidatorsKey
@ -36,10 +37,13 @@ prefixed areas of the staking store which are accessed in `x/stake/keeper.go`.
through this set to determine who we've kicked out.
retrieving validator by tendermint index
# Transient Store
The transient store persists between transations but not between blocks
## Tendermint Updates
- Prefix Key Space: TendermintUpdatesKey
- Prefix Key Space: TendermintUpdatesTKey
- Key/Sort: Validator Operator Address
- Value: Tendermint ABCI Validator
- Contains: Validators are queued to affect the consensus validation set in Tendermint
- Used For: Informing Tendermint of the validator set updates, is used only intra-block, as the
updates are applied then cleared on endblock
- Used For: Informing Tendermint of the validator set updates

View File

@ -11,6 +11,7 @@ import (
// keeper of the stake store
type Keeper struct {
storeKey sdk.StoreKey
storeTKey sdk.StoreKey
cdc *wire.Codec
bankKeeper bank.Keeper
validatorHooks sdk.ValidatorHooks
@ -19,9 +20,10 @@ type Keeper struct {
codespace sdk.CodespaceType
}
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
func NewKeeper(cdc *wire.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
keeper := Keeper{
storeKey: key,
storeTKey: tkey,
cdc: cdc,
bankKeeper: ck,
validatorHooks: nil,

View File

@ -22,14 +22,16 @@ var (
ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power
ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator
ValidatorPowerCliffKey = []byte{0x07} // key for the power of the validator on the cliff
TendermintUpdatesKey = []byte{0x08} // prefix for each key to a validator which is being updated
IntraTxCounterKey = []byte{0x09} // key for intra-block tx index
DelegationKey = []byte{0x0A} // key for a delegation
UnbondingDelegationKey = []byte{0x0B} // key for an unbonding-delegation
UnbondingDelegationByValIndexKey = []byte{0x0C} // prefix for each key for an unbonding-delegation, by validator operator
RedelegationKey = []byte{0x0D} // key for a redelegation
RedelegationByValSrcIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by source validator operator
RedelegationByValDstIndexKey = []byte{0x0F} // prefix for each key for an redelegation, by destination validator operator
IntraTxCounterKey = []byte{0x08} // key for intra-block tx index
DelegationKey = []byte{0x09} // key for a delegation
UnbondingDelegationKey = []byte{0x0A} // key for an unbonding-delegation
UnbondingDelegationByValIndexKey = []byte{0x0B} // prefix for each key for an unbonding-delegation, by validator operator
RedelegationKey = []byte{0x0C} // key for a redelegation
RedelegationByValSrcIndexKey = []byte{0x0D} // prefix for each key for an redelegation, by source validator operator
RedelegationByValDstIndexKey = []byte{0x0E} // prefix for each key for an redelegation, by destination validator operator
// Keys for store prefixes (transient)
TendermintUpdatesTKey = []byte{0x00} // prefix for each key to a validator which is being updated
)
const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch
@ -98,8 +100,8 @@ func getValidatorPowerRank(validator types.Validator, pool types.Pool) []byte {
// get the key for the accumulated update validators
// VALUE: abci.Validator
// note records using these keys should never persist between blocks
func GetTendermintUpdatesKey(operatorAddr sdk.ValAddress) []byte {
return append(TendermintUpdatesKey, operatorAddr.Bytes()...)
func GetTendermintUpdatesTKey(operatorAddr sdk.ValAddress) []byte {
return append(TendermintUpdatesTKey, operatorAddr.Bytes()...)
}
//______________________________________________________________________________

View File

@ -90,10 +90,12 @@ func ParamsNoInflation() types.Params {
func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context, auth.AccountMapper, Keeper) {
keyStake := sdk.NewKVStoreKey("stake")
tkeyStake := sdk.NewTransientStoreKey("transient_stake")
keyAcc := sdk.NewKVStoreKey("acc")
db := dbm.NewMemDB()
ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(tkeyStake, sdk.StoreTypeTransient, nil)
ms.MountStoreWithDB(keyStake, sdk.StoreTypeIAVL, db)
ms.MountStoreWithDB(keyAcc, sdk.StoreTypeIAVL, db)
err := ms.LoadLatestVersion()
@ -107,7 +109,7 @@ func CreateTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context
auth.ProtoBaseAccount, // prototype
)
ck := bank.NewBaseKeeper(accountMapper)
keeper := NewKeeper(cdc, keyStake, ck, types.DefaultCodespace)
keeper := NewKeeper(cdc, keyStake, tkeyStake, ck, types.DefaultCodespace)
keeper.SetPool(ctx, types.InitialPool())
keeper.SetNewParams(ctx, types.DefaultParams())
keeper.InitIntraTxCounter(ctx)

View File

@ -203,9 +203,9 @@ func (k Keeper) GetValidatorsByPower(ctx sdk.Context) []types.Validator {
// at the previous block height or were removed from the validator set entirely
// are returned to Tendermint.
func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Validator) {
store := ctx.KVStore(k.storeKey)
tstore := ctx.TransientStore(k.storeTKey)
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey)
iterator := sdk.KVStorePrefixIterator(tstore, TendermintUpdatesTKey)
for ; iterator.Valid(); iterator.Next() {
var abciVal abci.Validator
@ -233,18 +233,6 @@ func (k Keeper) GetValidTendermintUpdates(ctx sdk.Context) (updates []abci.Valid
return
}
// remove all validator update entries after applied to Tendermint
func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) {
store := ctx.KVStore(k.storeKey)
// delete subspace
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesKey)
for ; iterator.Valid(); iterator.Next() {
store.Delete(iterator.Key())
}
iterator.Close()
}
//___________________________________________________________________________
// Perform all the necessary steps for when a validator changes its power. This
@ -255,7 +243,7 @@ func (k Keeper) ClearTendermintUpdates(ctx sdk.Context) {
// nolint: gocyclo
// TODO: Remove above nolint, function needs to be simplified!
func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) types.Validator {
store := ctx.KVStore(k.storeKey)
tstore := ctx.TransientStore(k.storeTKey)
pool := k.GetPool(ctx)
oldValidator, oldFound := k.GetValidator(ctx, validator.OperatorAddr)
@ -280,7 +268,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
(oldFound && oldValidator.Status == sdk.Bonded):
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz)
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bz)
if cliffValExists {
cliffAddr := sdk.ValAddress(k.GetCliffValidator(ctx))
@ -315,7 +303,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type
// if decreased in power but still bonded, update Tendermint validator
if oldFound && oldValidator.BondedTokens().GT(validator.BondedTokens()) {
bz := k.cdc.MustMarshalBinary(validator.ABCIValidator())
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bz)
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bz)
}
}
@ -645,7 +633,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
// add to accumulated changes for tendermint
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI)
tstore := ctx.TransientStore(k.storeTKey)
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
// also remove from the Bonded types.Validators Store
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
@ -682,7 +671,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
// add to accumulated changes for tendermint
bzABCI := k.cdc.MustMarshalBinary(validator.ABCIValidator())
store.Set(GetTendermintUpdatesKey(validator.OperatorAddr), bzABCI)
tstore := ctx.TransientStore(k.storeTKey)
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
// call the bond hook if present
if k.validatorHooks != nil {
@ -717,7 +707,8 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
bz := k.cdc.MustMarshalBinary(validator.ABCIValidatorZero())
store.Set(GetTendermintUpdatesKey(address), bz)
tstore := ctx.TransientStore(k.storeTKey)
tstore.Set(GetTendermintUpdatesTKey(address), bz)
}
//__________________________________________________________________________

View File

@ -6,12 +6,25 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// for testing, remove all validator update entries after applied to Tendermint
func clearTendermintUpdates(ctx sdk.Context, k Keeper) {
store := ctx.TransientStore(k.storeTKey)
// delete subspace
iterator := sdk.KVStorePrefixIterator(store, TendermintUpdatesTKey)
for ; iterator.Valid(); iterator.Next() {
store.Delete(iterator.Key())
}
iterator.Close()
}
//_______________________________________________________
func TestSetValidator(t *testing.T) {
ctx, _, keeper := CreateTestInput(t, false, 10)
pool := keeper.GetPool(ctx)
@ -636,32 +649,6 @@ func TestFullValidatorSetPowerChange(t *testing.T) {
assert.True(ValEq(t, validators[2], resValidators[1]))
}
// clear the tracked changes to the gotValidator set
func TestClearTendermintUpdates(t *testing.T) {
ctx, _, keeper := CreateTestInput(t, false, 1000)
amts := []int64{100, 400, 200}
validators := make([]types.Validator, len(amts))
for i, amt := range amts {
pool := keeper.GetPool(ctx)
valPubKey := PKs[i]
valAddr := sdk.ValAddress(valPubKey.Address().Bytes())
validators[i] = types.NewValidator(valAddr, valPubKey, types.Description{})
validators[i], pool, _ = validators[i].AddTokensFromDel(pool, sdk.NewInt(amt))
keeper.SetPool(ctx, pool)
keeper.UpdateValidator(ctx, validators[i])
}
updates := keeper.GetValidTendermintUpdates(ctx)
require.Equal(t, len(amts), len(updates))
keeper.ClearTendermintUpdates(ctx)
updates = keeper.GetValidTendermintUpdates(ctx)
require.Equal(t, 0, len(updates))
}
func TestGetValidTendermintUpdatesAllNone(t *testing.T) {
ctx, _, keeper := CreateTestInput(t, false, 1000)
@ -688,21 +675,6 @@ func TestGetValidTendermintUpdatesAllNone(t *testing.T) {
assert.Equal(t, 2, len(updates))
assert.Equal(t, validators[0].ABCIValidator(), updates[0])
assert.Equal(t, validators[1].ABCIValidator(), updates[1])
// test from something to nothing
// tendermintUpdate set: {} -> {c1, c2, c3, c4}
keeper.ClearTendermintUpdates(ctx)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
keeper.RemoveValidator(ctx, validators[0].OperatorAddr)
keeper.RemoveValidator(ctx, validators[1].OperatorAddr)
updates = keeper.GetValidTendermintUpdates(ctx)
assert.Equal(t, 2, len(updates))
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[0].ConsPubKey), updates[0].PubKey)
assert.Equal(t, tmtypes.TM2PB.PubKey(validators[1].ConsPubKey), updates[1].PubKey)
assert.Equal(t, int64(0), updates[0].Power)
assert.Equal(t, int64(0), updates[1].Power)
}
func TestGetValidTendermintUpdatesIdentical(t *testing.T) {
@ -718,7 +690,7 @@ func TestGetValidTendermintUpdatesIdentical(t *testing.T) {
}
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// test identical,
@ -741,7 +713,7 @@ func TestGetValidTendermintUpdatesSingleValueChange(t *testing.T) {
}
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// test single value change
@ -769,7 +741,7 @@ func TestGetValidTendermintUpdatesMultipleValueChange(t *testing.T) {
}
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// test multiple value change
@ -800,7 +772,7 @@ func TestGetValidTendermintUpdatesInserted(t *testing.T) {
}
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// test validtor added at the beginning
@ -812,7 +784,7 @@ func TestGetValidTendermintUpdatesInserted(t *testing.T) {
// test validtor added at the beginning
// tendermintUpdate set: {} -> {c0}
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
validators[3] = keeper.UpdateValidator(ctx, validators[3])
updates = keeper.GetValidTendermintUpdates(ctx)
require.Equal(t, 1, len(updates))
@ -820,7 +792,7 @@ func TestGetValidTendermintUpdatesInserted(t *testing.T) {
// test validtor added at the end
// tendermintUpdate set: {} -> {c0}
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
validators[4] = keeper.UpdateValidator(ctx, validators[4])
updates = keeper.GetValidTendermintUpdates(ctx)
require.Equal(t, 1, len(updates))
@ -843,7 +815,7 @@ func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) {
}
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// test validator added at the end but not inserted in the valset
@ -854,7 +826,7 @@ func TestGetValidTendermintUpdatesWithCliffValidator(t *testing.T) {
// test validator change its power and become a gotValidator (pushing out an existing)
// tendermintUpdate set: {} -> {c0, c4}
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
pool := keeper.GetPool(ctx)
@ -881,7 +853,7 @@ func TestGetValidTendermintUpdatesPowerDecrease(t *testing.T) {
}
validators[0] = keeper.UpdateValidator(ctx, validators[0])
validators[1] = keeper.UpdateValidator(ctx, validators[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// check initial power
@ -937,7 +909,7 @@ func TestGetValidTendermintUpdatesNewValidator(t *testing.T) {
require.Equal(t, validators[0].ABCIValidator(), updates[0])
require.Equal(t, validators[1].ABCIValidator(), updates[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// update initial validator set
@ -1013,7 +985,7 @@ func TestGetValidTendermintUpdatesBondTransition(t *testing.T) {
require.Equal(t, validators[2].ABCIValidator(), updates[0])
require.Equal(t, validators[1].ABCIValidator(), updates[1])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
// delegate to validator with lowest power but not enough to bond
@ -1054,6 +1026,6 @@ func TestGetValidTendermintUpdatesBondTransition(t *testing.T) {
require.Equal(t, 1, len(updates))
require.Equal(t, validators[1].ABCIValidator(), updates[0])
keeper.ClearTendermintUpdates(ctx)
clearTendermintUpdates(ctx, keeper)
require.Equal(t, 0, len(keeper.GetValidTendermintUpdates(ctx)))
}

View File

@ -23,7 +23,8 @@ func TestStakeWithRandomMessages(t *testing.T) {
mapper := mapp.AccountMapper
bankKeeper := bank.NewBaseKeeper(mapper)
stakeKey := sdk.NewKVStoreKey("stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, bankKeeper, stake.DefaultCodespace)
stakeTKey := sdk.NewTransientStoreKey("transient_stake")
stakeKeeper := stake.NewKeeper(mapp.Cdc, stakeKey, stakeTKey, bankKeeper, stake.DefaultCodespace)
mapp.Router().AddRoute("stake", stake.NewHandler(stakeKeeper))
mapp.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
validatorUpdates := stake.EndBlocker(ctx, stakeKeeper)
@ -32,7 +33,7 @@ func TestStakeWithRandomMessages(t *testing.T) {
}
})
err := mapp.CompleteSetup([]*sdk.KVStoreKey{stakeKey})
err := mapp.CompleteSetup(stakeKey, stakeTKey)
if err != nil {
panic(err)
}

View File

@ -33,7 +33,7 @@ var (
GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
GetTendermintUpdatesKey = keeper.GetTendermintUpdatesKey
GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey
GetDelegationKey = keeper.GetDelegationKey
GetDelegationsKey = keeper.GetDelegationsKey
ParamKey = keeper.ParamKey
@ -44,7 +44,7 @@ var (
ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey
ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey
ValidatorPowerCliffKey = keeper.ValidatorPowerCliffKey
TendermintUpdatesKey = keeper.TendermintUpdatesKey
TendermintUpdatesTKey = keeper.TendermintUpdatesTKey
DelegationKey = keeper.DelegationKey
IntraTxCounterKey = keeper.IntraTxCounterKey
GetUBDKey = keeper.GetUBDKey