Skip to content

Commit

Permalink
Revert "Modify GetValidatorActiveSetChanges to use new state service (
Browse files Browse the repository at this point in the history
#5408)"

This reverts commit 5eb6485.
  • Loading branch information
terencechain committed Apr 16, 2020
1 parent 9db7f2d commit 04957cb
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 59 deletions.
88 changes: 52 additions & 36 deletions beacon-chain/rpc/beacon/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,18 +360,60 @@ func (bs *Server) GetValidator(
func (bs *Server) GetValidatorActiveSetChanges(
ctx context.Context, req *ethpb.GetValidatorActiveSetChangesRequest,
) (*ethpb.ActiveSetChanges, error) {
currentEpoch := helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot())
headState, err := bs.HeadFetcher.HeadState(ctx)
if err != nil {
return nil, status.Error(codes.Internal, "Could not get head state")
}
currentEpoch := helpers.CurrentEpoch(headState)
requestedEpoch := currentEpoch
requestingGenesis := false

var requestedEpoch uint64
switch q := req.QueryFilter.(type) {
case *ethpb.GetValidatorActiveSetChangesRequest_Genesis:
requestingGenesis = q.Genesis
requestedEpoch = 0
case *ethpb.GetValidatorActiveSetChangesRequest_Epoch:
requestedEpoch = q.Epoch
default:
requestedEpoch = currentEpoch
}
if requestedEpoch > currentEpoch {

activatedIndices := make([]uint64, 0)
exitedIndices := make([]uint64, 0)
slashedIndices := make([]uint64, 0)
ejectedIndices := make([]uint64, 0)
if requestingGenesis || requestedEpoch < currentEpoch {
archivedChanges, err := bs.BeaconDB.ArchivedActiveValidatorChanges(ctx, requestedEpoch)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not fetch archived active validator changes: %v", err)
}
if archivedChanges == nil {
return nil, status.Errorf(
codes.NotFound,
"Did not find any data for epoch %d - perhaps no active set changed occurred during the epoch",
requestedEpoch,
)
}
activatedIndices = archivedChanges.Activated
exitedIndices = archivedChanges.Exited
slashedIndices = archivedChanges.Slashed
ejectedIndices = archivedChanges.Ejected
} else if requestedEpoch == currentEpoch {
activeValidatorCount, err := helpers.ActiveValidatorCount(headState, helpers.PrevEpoch(headState))
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get active validator count: %v", err)
}
vals := headState.Validators()
activatedIndices = validators.ActivatedValidatorIndices(helpers.PrevEpoch(headState), vals)
exitedIndices, err = validators.ExitedValidatorIndices(helpers.PrevEpoch(headState), vals, activeValidatorCount)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine exited validator indices: %v", err)
}
slashedIndices = validators.SlashedValidatorIndices(helpers.PrevEpoch(headState), vals)
ejectedIndices, err = validators.EjectedValidatorIndices(helpers.PrevEpoch(headState), vals, activeValidatorCount)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine ejected validator indices: %v", err)
}
} else {
// We are requesting data from the future and we return an error.
return nil, status.Errorf(
codes.InvalidArgument,
"Cannot retrieve information about an epoch in the future, current epoch %d, requesting %d",
Expand All @@ -380,51 +422,25 @@ func (bs *Server) GetValidatorActiveSetChanges(
)
}

activatedIndices := make([]uint64, 0)
exitedIndices := make([]uint64, 0)
slashedIndices := make([]uint64, 0)
ejectedIndices := make([]uint64, 0)

requestedState, err := bs.StateGen.StateBySlot(ctx, helpers.StartSlot(requestedEpoch))
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get state: %v", err)
}

activeValidatorCount, err := helpers.ActiveValidatorCount(requestedState, helpers.CurrentEpoch(requestedState))
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get active validator count: %v", err)
}
vs := requestedState.Validators()
activatedIndices = validators.ActivatedValidatorIndices(helpers.CurrentEpoch(requestedState), vs)
exitedIndices, err = validators.ExitedValidatorIndices(helpers.CurrentEpoch(requestedState), vs, activeValidatorCount)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine exited validator indices: %v", err)
}
slashedIndices = validators.SlashedValidatorIndices(helpers.CurrentEpoch(requestedState), vs)
ejectedIndices, err = validators.EjectedValidatorIndices(helpers.CurrentEpoch(requestedState), vs, activeValidatorCount)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine ejected validator indices: %v", err)
}

// Retrieve public keys for the indices.
// We retrieve the public keys for the indices.
activatedKeys := make([][]byte, len(activatedIndices))
exitedKeys := make([][]byte, len(exitedIndices))
slashedKeys := make([][]byte, len(slashedIndices))
ejectedKeys := make([][]byte, len(ejectedIndices))
for i, idx := range activatedIndices {
pubkey := requestedState.PubkeyAtIndex(idx)
pubkey := headState.PubkeyAtIndex(idx)
activatedKeys[i] = pubkey[:]
}
for i, idx := range exitedIndices {
pubkey := requestedState.PubkeyAtIndex(idx)
pubkey := headState.PubkeyAtIndex(idx)
exitedKeys[i] = pubkey[:]
}
for i, idx := range slashedIndices {
pubkey := requestedState.PubkeyAtIndex(idx)
pubkey := headState.PubkeyAtIndex(idx)
slashedKeys[i] = pubkey[:]
}
for i, idx := range ejectedIndices {
pubkey := requestedState.PubkeyAtIndex(idx)
pubkey := headState.PubkeyAtIndex(idx)
ejectedKeys[i] = pubkey[:]
}
return &ethpb.ActiveSetChanges{
Expand Down
149 changes: 126 additions & 23 deletions beacon-chain/rpc/beacon/validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1122,19 +1122,27 @@ func TestServer_GetValidator(t *testing.T) {
}

func TestServer_GetValidatorActiveSetChanges_CannotRequestFutureEpoch(t *testing.T) {
db := dbTest.SetupDB(t)
defer dbTest.TeardownDB(t, db)

ctx := context.Background()
st := testutil.NewBeaconState()
if err := st.SetSlot(0); err != nil {
t.Fatal(err)
}
bs := &Server{GenesisTimeFetcher: &mock.ChainService{}}
bs := &Server{
BeaconDB: db,
HeadFetcher: &mock.ChainService{
State: st,
},
}

wanted := "Cannot retrieve information about an epoch in the future"
if _, err := bs.GetValidatorActiveSetChanges(
ctx,
&ethpb.GetValidatorActiveSetChangesRequest{
QueryFilter: &ethpb.GetValidatorActiveSetChangesRequest_Epoch{
Epoch: helpers.SlotToEpoch(bs.GenesisTimeFetcher.CurrentSlot()) + 1,
Epoch: 1,
},
},
); err != nil && !strings.Contains(err.Error(), wanted) {
Expand All @@ -1143,9 +1151,6 @@ func TestServer_GetValidatorActiveSetChanges_CannotRequestFutureEpoch(t *testing
}

func TestServer_GetValidatorActiveSetChanges(t *testing.T) {
db := dbTest.SetupDB(t)
defer dbTest.TeardownDB(t, db)

ctx := context.Background()
validators := make([]*ethpb.Validator, 8)
headState := testutil.NewBeaconState()
Expand Down Expand Up @@ -1190,52 +1195,140 @@ func TestServer_GetValidatorActiveSetChanges(t *testing.T) {
t.Fatal(err)
}
}
b := &ethpb.SignedBeaconBlock{Block: &ethpb.BeaconBlock{}}
if err := db.SaveBlock(ctx, b); err != nil {
bs := &Server{
HeadFetcher: &mock.ChainService{
State: headState,
},
FinalizationFetcher: &mock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{Epoch: 0},
},
}
res, err := bs.GetValidatorActiveSetChanges(ctx, &ethpb.GetValidatorActiveSetChangesRequest{})
if err != nil {
t.Fatal(err)
}
wantedActive := [][]byte{
pubKey(0),
pubKey(2),
pubKey(4),
pubKey(6),
}
wantedActiveIndices := []uint64{0, 2, 4, 6}
wantedExited := [][]byte{
pubKey(5),
}
wantedExitedIndices := []uint64{5}
wantedSlashed := [][]byte{
pubKey(3),
}
wantedSlashedIndices := []uint64{3}
wantedEjected := [][]byte{
pubKey(7),
}
wantedEjectedIndices := []uint64{7}
wanted := &ethpb.ActiveSetChanges{
Epoch: 0,
ActivatedPublicKeys: wantedActive,
ActivatedIndices: wantedActiveIndices,
ExitedPublicKeys: wantedExited,
ExitedIndices: wantedExitedIndices,
SlashedPublicKeys: wantedSlashed,
SlashedIndices: wantedSlashedIndices,
EjectedPublicKeys: wantedEjected,
EjectedIndices: wantedEjectedIndices,
}
if !proto.Equal(wanted, res) {
t.Errorf("Wanted \n%v, received \n%v", wanted, res)
}
}

gRoot, err := ssz.HashTreeRoot(b.Block)
if err != nil {
func TestServer_GetValidatorActiveSetChanges_FromArchive(t *testing.T) {
db := dbTest.SetupDB(t)
defer dbTest.TeardownDB(t, db)
ctx := context.Background()
validators := make([]*ethpb.Validator, 8)
headState := testutil.NewBeaconState()
if err := headState.SetSlot(helpers.StartSlot(100)); err != nil {
t.Fatal(err)
}
if err := headState.SetValidators(validators); err != nil {
t.Fatal(err)
}
if err := db.SaveGenesisBlockRoot(ctx, gRoot); err != nil {
activatedIndices := make([]uint64, 0)
exitedIndices := make([]uint64, 0)
slashedIndices := make([]uint64, 0)
ejectedIndices := make([]uint64, 0)
for i := 0; i < len(validators); i++ {
// Mark indices divisible by two as activated.
if i%2 == 0 {
activatedIndices = append(activatedIndices, uint64(i))
} else if i%3 == 0 {
// Mark indices divisible by 3 as slashed.
slashedIndices = append(slashedIndices, uint64(i))
} else if i%5 == 0 {
// Mark indices divisible by 5 as exited.
exitedIndices = append(exitedIndices, uint64(i))
} else if i%7 == 0 {
// Mark indices divisible by 7 as ejected.
ejectedIndices = append(ejectedIndices, uint64(i))
}
key := make([]byte, 48)
copy(key, strconv.Itoa(i))
if err := headState.UpdateValidatorAtIndex(uint64(i), &ethpb.Validator{
PublicKey: key,
}); err != nil {
t.Fatal(err)
}
}
archivedChanges := &pbp2p.ArchivedActiveSetChanges{
Activated: activatedIndices,
Exited: exitedIndices,
Slashed: slashedIndices,
Ejected: ejectedIndices,
}
// We store the changes during the genesis epoch.
if err := db.SaveArchivedActiveValidatorChanges(ctx, 0, archivedChanges); err != nil {
t.Fatal(err)
}
if err := db.SaveState(ctx, headState, gRoot); err != nil {
// We store the same changes during epoch 5 for further testing.
if err := db.SaveArchivedActiveValidatorChanges(ctx, 5, archivedChanges); err != nil {
t.Fatal(err)
}

bs := &Server{
FinalizationFetcher: &mock.ChainService{
FinalizedCheckPoint: &ethpb.Checkpoint{Epoch: 0},
BeaconDB: db,
HeadFetcher: &mock.ChainService{
State: headState,
},
GenesisTimeFetcher: &mock.ChainService{},
StateGen: stategen.New(db, cache.NewStateSummaryCache()),
}
res, err := bs.GetValidatorActiveSetChanges(ctx, &ethpb.GetValidatorActiveSetChangesRequest{
QueryFilter: &ethpb.GetValidatorActiveSetChangesRequest_Genesis{Genesis: true},
})
if err != nil {
t.Fatal(err)
}
wantedKeys := make([][]byte, 8)
for i := 0; i < len(wantedKeys); i++ {
k := make([]byte, 48)
copy(k, strconv.Itoa(i))
wantedKeys[i] = k
}
wantedActive := [][]byte{
pubKey(0),
pubKey(2),
pubKey(4),
pubKey(6),
wantedKeys[0],
wantedKeys[2],
wantedKeys[4],
wantedKeys[6],
}
wantedActiveIndices := []uint64{0, 2, 4, 6}
wantedExited := [][]byte{
pubKey(5),
wantedKeys[5],
}
wantedExitedIndices := []uint64{5}
wantedSlashed := [][]byte{
pubKey(3),
wantedKeys[3],
}
wantedSlashedIndices := []uint64{3}
wantedEjected := [][]byte{
pubKey(7),
wantedKeys[7],
}
wantedEjectedIndices := []uint64{7}
wanted := &ethpb.ActiveSetChanges{
Expand All @@ -1252,6 +1345,16 @@ func TestServer_GetValidatorActiveSetChanges(t *testing.T) {
if !proto.Equal(wanted, res) {
t.Errorf("Wanted \n%v, received \n%v", wanted, res)
}
res, err = bs.GetValidatorActiveSetChanges(ctx, &ethpb.GetValidatorActiveSetChangesRequest{
QueryFilter: &ethpb.GetValidatorActiveSetChangesRequest_Epoch{Epoch: 5},
})
if err != nil {
t.Fatal(err)
}
wanted.Epoch = 5
if !proto.Equal(wanted, res) {
t.Errorf("Wanted \n%v, received \n%v", wanted, res)
}
}

func TestServer_GetValidatorQueue_PendingActivation(t *testing.T) {
Expand Down

0 comments on commit 04957cb

Please sign in to comment.