Save and Delete Validators Pubkey - Idx Post Chainstart (#1873)

* starting tests

* added tests

* fixed comments

* gaz

* make sure key is using EntryExitEffectEpoch
This commit is contained in:
terence tsao 2019-03-04 23:22:15 -08:00 committed by Nishant Das
parent 9999b3280a
commit dd40320a1c
4 changed files with 133 additions and 0 deletions

View File

@ -12,6 +12,7 @@ go_library(
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
@ -36,6 +37,7 @@ go_test(
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/state:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/internal:go_default_library",
"//beacon-chain/powchain:go_default_library",

View File

@ -11,7 +11,9 @@ import (
"github.com/ethereum/go-ethereum/common"
gethTypes "github.com/ethereum/go-ethereum/core/types"
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
@ -347,6 +349,14 @@ func (c *ChainService) ReceiveBlock(block *pb.BeaconBlock, beaconState *pb.Beaco
"slotsSinceGenesis", beaconState.Slot-params.BeaconConfig().GenesisSlot,
).Info("Block transition successfully processed")
if (beaconState.Slot+1)%params.BeaconConfig().SlotsPerEpoch == 0 {
// Save activated validators of this epoch to public key -> index DB.
if err := c.saveValidatorIdx(beaconState); err != nil {
return nil, fmt.Errorf("could not save validator index: %v", err)
}
// Delete exited validators of this epoch to public key -> index DB.
if err := c.deleteValidatorIdx(beaconState); err != nil {
return nil, fmt.Errorf("could not delete validator index: %v", err)
}
log.WithField(
"SlotsSinceGenesis", beaconState.Slot-params.BeaconConfig().GenesisSlot,
).Info("Epoch transition successfully processed")
@ -380,3 +390,31 @@ func (c *ChainService) isBlockReadyForProcessing(block *pb.BeaconBlock, beaconSt
}
return nil
}
// saveValidatorIdx saves the validators public key to index mapping in DB, these
// validators were activated from current epoch. After it saves, current epoch key
// is deleted from ActivatedValidators mapping.
func (c *ChainService) saveValidatorIdx(state *pb.BeaconState) error {
for _, idx := range validators.ActivatedValidators[helpers.CurrentEpoch(state)] {
pubKey := state.ValidatorRegistry[idx].Pubkey
if err := c.beaconDB.SaveValidatorIndex(pubKey, int(idx)); err != nil {
return fmt.Errorf("could not save validator index: %v", err)
}
}
delete(validators.ActivatedValidators, helpers.CurrentEpoch(state))
return nil
}
// deleteValidatorIdx deletes the validators public key to index mapping in DB, the
// validators were exited from current epoch. After it deletes, current epoch key
// is deleted from ExitedValidators mapping.
func (c *ChainService) deleteValidatorIdx(state *pb.BeaconState) error {
for _, idx := range validators.ExitedValidators[helpers.CurrentEpoch(state)] {
pubKey := state.ValidatorRegistry[idx].Pubkey
if err := c.beaconDB.DeleteValidatorIndex(pubKey); err != nil {
return fmt.Errorf("could not delete validator index: %v", err)
}
}
delete(validators.ExitedValidators, helpers.CurrentEpoch(state))
return nil
}

View File

@ -16,6 +16,7 @@ import (
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
@ -709,3 +710,83 @@ func TestIsBlockReadyForProcessing_ValidBlock(t *testing.T) {
t.Fatalf("block processing failed despite being a valid block: %v", err)
}
}
func TestDeleteValidatorIdx_DeleteWorks(t *testing.T) {
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
epoch := uint64(2)
v.ActivatedValidators[epoch] = []uint64{0, 1, 2}
v.ExitedValidators[epoch] = []uint64{0, 2}
var validators []*pb.Validator
for i := 0; i < 3; i++ {
pubKeyBuf := make([]byte, params.BeaconConfig().BLSPubkeyLength)
binary.PutUvarint(pubKeyBuf, uint64(i))
validators = append(validators, &pb.Validator{
Pubkey: pubKeyBuf,
})
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
}
chainService := setupBeaconChain(t, false, db, true)
if err := chainService.saveValidatorIdx(state); err != nil {
t.Fatalf("Could not save validator idx: %v", err)
}
if err := chainService.deleteValidatorIdx(state); err != nil {
t.Fatalf("Could not delete validator idx: %v", err)
}
wantedIdx := uint64(1)
idx, err := chainService.beaconDB.ValidatorIndex(validators[wantedIdx].Pubkey)
if err != nil {
t.Fatalf("Could not get validator index: %v", err)
}
if wantedIdx != idx {
t.Errorf("Wanted: %d, got: %d", wantedIdx, idx)
}
wantedIdx = uint64(2)
if chainService.beaconDB.HasValidator(validators[wantedIdx].Pubkey) {
t.Errorf("Validator index %d should have been deleted", wantedIdx)
}
if _, ok := v.ExitedValidators[epoch]; ok {
t.Errorf("Activated validators mapping for epoch %d still there", epoch)
}
}
func TestSaveValidatorIdx_SaveRetrieveWorks(t *testing.T) {
db := internal.SetupDB(t)
defer internal.TeardownDB(t, db)
epoch := uint64(1)
v.ActivatedValidators[epoch] = []uint64{0, 1, 2}
var validators []*pb.Validator
for i := 0; i < 3; i++ {
pubKeyBuf := make([]byte, params.BeaconConfig().BLSPubkeyLength)
binary.PutUvarint(pubKeyBuf, uint64(i))
validators = append(validators, &pb.Validator{
Pubkey: pubKeyBuf,
})
}
state := &pb.BeaconState{
ValidatorRegistry: validators,
Slot: epoch * params.BeaconConfig().SlotsPerEpoch,
}
chainService := setupBeaconChain(t, false, db, true)
if err := chainService.saveValidatorIdx(state); err != nil {
t.Fatalf("Could not save validator idx: %v", err)
}
wantedIdx := uint64(2)
idx, err := chainService.beaconDB.ValidatorIndex(validators[wantedIdx].Pubkey)
if err != nil {
t.Fatalf("Could not get validator index: %v", err)
}
if wantedIdx != idx {
t.Errorf("Wanted: %d, got: %d", wantedIdx, idx)
}
if _, ok := v.ActivatedValidators[epoch]; ok {
t.Errorf("Activated validators mapping for epoch %d still there", epoch)
}
}

View File

@ -15,6 +15,15 @@ import (
"github.com/prysmaticlabs/prysm/shared/sliceutil"
)
var (
// ActivatedValidators is a mapping that tracks epoch to activated validators indexes.
// Where key is epoch, value is a list of activated validator indexes.
ActivatedValidators = make(map[uint64][]uint64)
// ExitedValidators is a mapping that tracks epoch to excited validators indexes.
// Where key is epoch, value is a list of exited validator indexes.
ExitedValidators = make(map[uint64][]uint64)
)
// ValidatorIndices returns all the validator indices from the input attestations
// and state.
//
@ -279,6 +288,7 @@ func SlashValidator(state *pb.BeaconState, idx uint64) (*pb.BeaconState, error)
// state.validator_registry_update_epoch = current_epoch
func UpdateRegistry(state *pb.BeaconState) (*pb.BeaconState, error) {
currentEpoch := helpers.CurrentEpoch(state)
updatedEpoch := helpers.EntryExitEffectEpoch(currentEpoch)
activeValidatorIndices := helpers.ActiveValidatorIndices(
state.ValidatorRegistry, currentEpoch)
@ -301,6 +311,7 @@ func UpdateRegistry(state *pb.BeaconState) (*pb.BeaconState, error) {
if err != nil {
return nil, fmt.Errorf("could not activate validator %d: %v", idx, err)
}
ActivatedValidators[updatedEpoch] = append(ActivatedValidators[updatedEpoch], uint64(idx))
}
}
@ -314,6 +325,7 @@ func UpdateRegistry(state *pb.BeaconState) (*pb.BeaconState, error) {
break
}
state = ExitValidator(state, uint64(idx))
ExitedValidators[updatedEpoch] = append(ExitedValidators[updatedEpoch], uint64(idx))
}
}
state.ValidatorRegistryUpdateEpoch = currentEpoch