diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index 3cd81202ae..c4a558b916 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -889,21 +889,21 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 1, len(keeper.GetValidatorsBonded(ctx))) + require.Equal(t, 1, len(keeper.GetLastValidators(ctx))) msgCreateValidator = NewTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 30) got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx))) + require.Equal(t, 2, len(keeper.GetLastValidators(ctx))) msgCreateValidator = NewTestMsgCreateValidator(validatorAddr3, keep.PKs[2], 10) got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") // apply TM updates keeper.ApplyAndReturnValidatorSetUpdates(ctx) - require.Equal(t, 2, len(keeper.GetValidatorsBonded(ctx))) + require.Equal(t, 2, len(keeper.GetLastValidators(ctx))) // unbond the valdator-2 msgBeginUnbonding := NewMsgBeginUnbonding(sdk.AccAddress(validatorAddr2), validatorAddr2, sdk.NewDec(30)) @@ -916,7 +916,7 @@ func TestUnbondingWhenExcessValidators(t *testing.T) { // because there are extra validators waiting to get in, the queued // validator (aka. validator-1) should make it into the bonded group, thus // the total number of validators should stay the same - vals := keeper.GetValidatorsBonded(ctx) + vals := keeper.GetLastValidators(ctx) require.Equal(t, 2, len(vals), "vals %v", vals) val1, found := keeper.GetValidator(ctx, validatorAddr1) require.True(t, found) diff --git a/x/stake/keeper/key.go b/x/stake/keeper/key.go index 91ea7d709c..6faf36b750 100644 --- a/x/stake/keeper/key.go +++ b/x/stake/keeper/key.go @@ -15,21 +15,27 @@ var ( // Keys for store prefixes // TODO DEPRECATED: delete in next release and reorder keys // ParamKey = []byte{0x00} // key for parameters relating to staking - PoolKey = []byte{0x01} // key for the staking pools - ValidatorsKey = []byte{0x02} // prefix for each key to a validator - ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey - ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators - ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power - IntraTxCounterKey = []byte{0x06} // key for intra-block tx index - DelegationKey = []byte{0x07} // key for a delegation - UnbondingDelegationKey = []byte{0x08} // key for an unbonding-delegation - UnbondingDelegationByValIndexKey = []byte{0x09} // prefix for each key for an unbonding-delegation, by validator operator - RedelegationKey = []byte{0x0A} // key for a redelegation - RedelegationByValSrcIndexKey = []byte{0x0B} // prefix for each key for an redelegation, by source validator operator - RedelegationByValDstIndexKey = []byte{0x0C} // prefix for each key for an redelegation, by destination validator operator - UnbondingQueueKey = []byte{0x0D} // prefix for the timestamps in unbonding queue - RedelegationQueueKey = []byte{0x0E} // prefix for the timestamps in redelegations queue - ValidatorQueueKey = []byte{0x0F} // prefix for the timestamps in validator queue + PoolKey = []byte{0x01} // key for the staking pools + IntraTxCounterKey = []byte{0x02} // key for intra-block tx index + + // Last* values are const during a block. + LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators + LastTotalPowerKey = []byte{0x12} // prefix for each key to a validator index, for bonded validators + + ValidatorsKey = []byte{0x21} // prefix for each key to a validator + ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey + ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power + + DelegationKey = []byte{0x31} // key for a delegation + UnbondingDelegationKey = []byte{0x32} // key for an unbonding-delegation + UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator + RedelegationKey = []byte{0x34} // key for a redelegation + RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator + RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator + + UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue + RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue + ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue ) const maxDigitsForAccount = 12 // ~220,000,000 atoms created at launch @@ -46,9 +52,9 @@ func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { return append(ValidatorsByConsAddrKey, addr.Bytes()...) } -// Get the validator operator address from ValBondedIndexKey -func GetAddressFromValBondedIndexKey(IndexKey []byte) []byte { - return IndexKey[1:] // remove prefix bytes +// Get the validator operator address from LastValidatorPowerKey +func AddressFromLastValidatorPowerKey(key []byte) []byte { + return key[1:] // remove prefix bytes } // get the validator by power index. @@ -61,8 +67,8 @@ func GetValidatorsByPowerIndexKey(validator types.Validator, pool types.Pool) [] } // get the bonded validator index key for an operator address -func GetValidatorsBondedIndexKey(operator sdk.ValAddress) []byte { - return append(ValidatorsBondedIndexKey, operator...) +func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { + return append(LastValidatorPowerKey, operator...) } // get the power ranking of a validator diff --git a/x/stake/keeper/key_test.go b/x/stake/keeper/key_test.go index dfd6a44e79..385f313c15 100644 --- a/x/stake/keeper/key_test.go +++ b/x/stake/keeper/key_test.go @@ -35,10 +35,10 @@ func TestGetValidatorPowerRank(t *testing.T) { validator types.Validator wantHex string }{ - {val1, "050000000000000000ffffffffffffffffffff"}, - {val2, "050000000000000001ffffffffffffffffffff"}, - {val3, "05000000000000000affffffffffffffffffff"}, - {val4, "050000010000000000ffffffffffffffffffff"}, + {val1, "230000000000000000ffffffffffffffffffff"}, + {val2, "230000000000000001ffffffffffffffffffff"}, + {val3, "23000000000000000affffffffffffffffffff"}, + {val4, "230000010000000000ffffffffffffffffffff"}, } for i, tt := range tests { got := hex.EncodeToString(getValidatorPowerRank(tt.validator)) @@ -55,11 +55,11 @@ func TestGetREDByValDstIndexKey(t *testing.T) { wantHex string }{ {sdk.AccAddress(addr1), sdk.ValAddress(addr1), sdk.ValAddress(addr1), - "0c63d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, + "3663d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, {sdk.AccAddress(addr1), sdk.ValAddress(addr2), sdk.ValAddress(addr3), - "0c3ab62f0d93849be495e21e3e9013a517038f45bd63d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f2"}, + "363ab62f0d93849be495e21e3e9013a517038f45bd63d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f2"}, {sdk.AccAddress(addr2), sdk.ValAddress(addr1), sdk.ValAddress(addr3), - "0c3ab62f0d93849be495e21e3e9013a517038f45bd5ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f08609"}, + "363ab62f0d93849be495e21e3e9013a517038f45bd5ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f08609"}, } for i, tt := range tests { got := hex.EncodeToString(GetREDByValDstIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr)) @@ -76,11 +76,11 @@ func TestGetREDByValSrcIndexKey(t *testing.T) { wantHex string }{ {sdk.AccAddress(addr1), sdk.ValAddress(addr1), sdk.ValAddress(addr1), - "0b63d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, + "3563d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, {sdk.AccAddress(addr1), sdk.ValAddress(addr2), sdk.ValAddress(addr3), - "0b5ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f086093ab62f0d93849be495e21e3e9013a517038f45bd"}, + "355ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f086093ab62f0d93849be495e21e3e9013a517038f45bd"}, {sdk.AccAddress(addr2), sdk.ValAddress(addr1), sdk.ValAddress(addr3), - "0b63d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f23ab62f0d93849be495e21e3e9013a517038f45bd"}, + "3563d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f23ab62f0d93849be495e21e3e9013a517038f45bd"}, } for i, tt := range tests { got := hex.EncodeToString(GetREDByValSrcIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr)) diff --git a/x/stake/keeper/sdk_types.go b/x/stake/keeper/sdk_types.go index 6672843566..976dcbe65e 100644 --- a/x/stake/keeper/sdk_types.go +++ b/x/stake/keeper/sdk_types.go @@ -30,10 +30,10 @@ func (k Keeper) IterateValidators(ctx sdk.Context, fn func(index int64, validato // iterate through the active validator set and perform the provided function func (k Keeper) IterateValidatorsBonded(ctx sdk.Context, fn func(index int64, validator sdk.Validator) (stop bool)) { store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) + iterator := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey) i := int64(0) for ; iterator.Valid(); iterator.Next() { - address := GetAddressFromValBondedIndexKey(iterator.Key()) + address := AddressFromLastValidatorPowerKey(iterator.Key()) validator, found := k.GetValidator(ctx, address) if !found { panic(fmt.Sprintf("validator record not found for address: %v\n", address)) diff --git a/x/stake/keeper/val_state_change.go b/x/stake/keeper/val_state_change.go index 2c832a8ad2..59f8b6deb2 100644 --- a/x/stake/keeper/val_state_change.go +++ b/x/stake/keeper/val_state_change.go @@ -12,10 +12,12 @@ import ( ) // Apply and return accumulated updates to the bonded validator set. Also, -// * Updates the active bonded valset as keyed by GetValidatorsBondedIndexKey(). +// * Updates the active bonded valset as keyed by LastValidatorPowerKey(). // * Updates validator status' according to updated powers. // * Updates the fee pool bonded vs loose tokens. // * Updates relevant indices. +// It gets called once after genesis, another time maybe after genesis transactions, +// then once at every EndBlock. // // CONTRACT: Only validators with non-zero power or zero-power that were bonded // at the previous block height or were removed from the validator set entirely @@ -27,10 +29,10 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab // Retrieve the last validator set. // This persistent set is updated later in this function. - // (see GetValidatorsBondedIndexKey()). + // (see LastValidatorPowerKey). last := k.retrieveLastValidatorSet(ctx) - // iterate over validators, highest power to lowest + // Iterate over validators, highest power to lowest. iterator := sdk.KVStoreReversePrefixIterator(store, ValidatorsByPowerIndexKey) count := 0 for ; iterator.Valid() && count < int(maxValidators); iterator.Next() { @@ -79,7 +81,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab delete(last, operatorBytes) // set the bonded validator index - store.Set(GetValidatorsBondedIndexKey(operator), newPowerBytes) + store.Set(GetLastValidatorPowerKey(operator), newPowerBytes) // keep count count++ @@ -104,7 +106,7 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab } // delete from the bonded validator index - store.Delete(GetValidatorsBondedIndexKey(operator)) + store.Delete(GetLastValidatorPowerKey(operator)) // update the validator set updates = append(updates, validator.ABCIValidatorUpdateZero()) @@ -247,7 +249,7 @@ type validatorsByAddr map[[sdk.AddrLen]byte][]byte func (k Keeper) retrieveLastValidatorSet(ctx sdk.Context) validatorsByAddr { last := make(validatorsByAddr) store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) + iterator := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey) for ; iterator.Valid(); iterator.Next() { var operator [sdk.AddrLen]byte copy(operator[:], iterator.Key()[1:]) diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 95e5f00012..9fd7434d31 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -235,24 +235,24 @@ func (k Keeper) GetValidators(ctx sdk.Context, maxRetrieve uint16) (validators [ } // get the group of the bonded validators -func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validator) { +func (k Keeper) GetLastValidators(ctx sdk.Context) (validators []types.Validator) { store := ctx.KVStore(k.storeKey) // add the actual validator power sorted store maxValidators := k.MaxValidators(ctx) validators = make([]types.Validator, maxValidators) - iterator := sdk.KVStorePrefixIterator(store, ValidatorsBondedIndexKey) + iterator := sdk.KVStorePrefixIterator(store, LastValidatorPowerKey) defer iterator.Close() i := 0 for ; iterator.Valid(); iterator.Next() { // sanity check - if i > int(maxValidators-1) { - panic("maxValidators is less than the number of records in ValidatorsBonded Store, store should have been updated") + if i >= int(maxValidators) { + panic("more validators than maxValidators found") } - address := GetAddressFromValBondedIndexKey(iterator.Key()) + address := AddressFromLastValidatorPowerKey(iterator.Key()) validator := k.mustGetValidator(ctx, address) validators[i] = validator @@ -261,7 +261,7 @@ func (k Keeper) GetValidatorsBonded(ctx sdk.Context) (validators []types.Validat return validators[:i] // trim } -// get the group of bonded validators sorted by power-rank +// get the current group of bonded validators sorted by power-rank func (k Keeper) GetBondedValidatorsByPower(ctx sdk.Context) []types.Validator { store := ctx.KVStore(k.storeKey) maxValidators := k.MaxValidators(ctx) diff --git a/x/stake/keeper/validator_test.go b/x/stake/keeper/validator_test.go index 6f14ba7a5d..7acf1cc02d 100644 --- a/x/stake/keeper/validator_test.go +++ b/x/stake/keeper/validator_test.go @@ -49,7 +49,7 @@ func TestSetValidator(t *testing.T) { assert.True(ValEq(t, validator, resVal)) require.True(t, found) - resVals := keeper.GetValidatorsBonded(ctx) + resVals := keeper.GetLastValidators(ctx) require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validator, resVals[0])) @@ -191,7 +191,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { require.False(t, found) } -// This function tests UpdateValidator, GetValidator, GetValidatorsBonded, RemoveValidator +// This function tests UpdateValidator, GetValidator, GetLastValidators, RemoveValidator func TestValidatorBasics(t *testing.T) { ctx, _, keeper := CreateTestInput(t, false, 1000) pool := keeper.GetPool(ctx) @@ -213,7 +213,7 @@ func TestValidatorBasics(t *testing.T) { // check the empty keeper first _, found := keeper.GetValidator(ctx, addrVals[0]) require.False(t, found) - resVals := keeper.GetValidatorsBonded(ctx) + resVals := keeper.GetLastValidators(ctx) require.Zero(t, len(resVals)) resVals = keeper.GetValidators(ctx, 2) @@ -237,7 +237,7 @@ func TestValidatorBasics(t *testing.T) { require.True(t, found) assert.True(ValEq(t, validators[0], resVal)) - resVals = keeper.GetValidatorsBonded(ctx) + resVals = keeper.GetLastValidators(ctx) require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validators[0], resVals[0])) assert.Equal(t, sdk.Bonded, validators[0].Status) @@ -255,7 +255,7 @@ func TestValidatorBasics(t *testing.T) { require.True(t, found) assert.True(ValEq(t, validators[0], resVal)) - resVals = keeper.GetValidatorsBonded(ctx) + resVals = keeper.GetLastValidators(ctx) require.Equal(t, 1, len(resVals)) assert.True(ValEq(t, validators[0], resVals[0])) @@ -269,7 +269,7 @@ func TestValidatorBasics(t *testing.T) { require.True(t, found) assert.True(ValEq(t, validators[2], resVal)) - resVals = keeper.GetValidatorsBonded(ctx) + resVals = keeper.GetLastValidators(ctx) require.Equal(t, 3, len(resVals)) assert.True(ValEq(t, validators[0], resVals[0])) // order doesn't matter here assert.True(ValEq(t, validators[1], resVals[1])) diff --git a/x/stake/stake.go b/x/stake/stake.go index c4aa547022..c755e352aa 100644 --- a/x/stake/stake.go +++ b/x/stake/stake.go @@ -39,12 +39,13 @@ var ( GetDelegationKey = keeper.GetDelegationKey GetDelegationsKey = keeper.GetDelegationsKey PoolKey = keeper.PoolKey + IntraTxCounterKey = keeper.IntraTxCounterKey + LastValidatorPowerKey = keeper.LastValidatorPowerKey + LastTotalPowerKey = keeper.LastTotalPowerKey ValidatorsKey = keeper.ValidatorsKey ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey - ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey DelegationKey = keeper.DelegationKey - IntraTxCounterKey = keeper.IntraTxCounterKey GetUBDKey = keeper.GetUBDKey GetUBDByValIndexKey = keeper.GetUBDByValIndexKey GetUBDsKey = keeper.GetUBDsKey