mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
ETH2 APIs: Implement Validator Status support (#8940)
* Update protos for new changes * Begin implementing validator status * Add support for validator status to state/validators * Fix nil pointer
This commit is contained in:
@@ -30,11 +30,13 @@ func (bs *Server) GetValidator(ctx context.Context, req *ethpb.StateValidatorReq
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get validator container: %v", err)
|
||||
}
|
||||
if len(valContainer) == 0 {
|
||||
return nil, status.Error(codes.NotFound, "Could not find validator")
|
||||
}
|
||||
return ðpb.StateValidatorResponse{Data: valContainer[0]}, nil
|
||||
}
|
||||
|
||||
// ListValidators returns filterable list of validators with their balance, status and index.
|
||||
// TODO(#8901): missing status support.
|
||||
func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidatorsRequest) (*ethpb.StateValidatorsResponse, error) {
|
||||
state, err := bs.StateFetcher.State(ctx, req.StateId)
|
||||
if err != nil {
|
||||
@@ -46,7 +48,24 @@ func (bs *Server) ListValidators(ctx context.Context, req *ethpb.StateValidators
|
||||
return nil, status.Errorf(codes.Internal, "Could not get validator container: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.StateValidatorsResponse{Data: valContainers}, nil
|
||||
if len(req.Status) == 0 {
|
||||
return ðpb.StateValidatorsResponse{Data: valContainers}, nil
|
||||
}
|
||||
|
||||
filterStatus := make(map[ethpb.ValidatorStatus]bool, len(req.Status))
|
||||
for _, ss := range req.Status {
|
||||
filterStatus[ss] = true
|
||||
}
|
||||
epoch := helpers.SlotToEpoch(state.Slot())
|
||||
filteredVals := make([]*ethpb.ValidatorContainer, 0, len(valContainers))
|
||||
for _, vc := range valContainers {
|
||||
valStatus := validatorStatus(vc.Validator, epoch)
|
||||
valSubStatus := validatorSubStatus(vc.Validator, epoch)
|
||||
if filterStatus[valStatus] || filterStatus[valSubStatus] {
|
||||
filteredVals = append(filteredVals, vc)
|
||||
}
|
||||
}
|
||||
return ðpb.StateValidatorsResponse{Data: filteredVals}, nil
|
||||
}
|
||||
|
||||
// ListValidatorBalances returns a filterable list of validator balances.
|
||||
@@ -123,16 +142,19 @@ func (bs *Server) ListCommittees(ctx context.Context, req *ethpb.StateCommittees
|
||||
// This function returns the validator object based on the passed in ID. The validator ID could be its public key,
|
||||
// or its index.
|
||||
func valContainersByRequestIds(state iface.BeaconState, validatorIds [][]byte) ([]*ethpb.ValidatorContainer, error) {
|
||||
epoch := helpers.SlotToEpoch(state.Slot())
|
||||
allValidators := state.Validators()
|
||||
allBalances := state.Balances()
|
||||
var valContainers []*ethpb.ValidatorContainer
|
||||
if len(validatorIds) == 0 {
|
||||
valContainers = make([]*ethpb.ValidatorContainer, len(allValidators))
|
||||
for i, validator := range allValidators {
|
||||
v1Validator := migration.V1Alpha1ValidatorToV1(validator)
|
||||
valContainers[i] = ðpb.ValidatorContainer{
|
||||
Index: types.ValidatorIndex(i),
|
||||
Balance: allBalances[i],
|
||||
Validator: migration.V1Alpha1ValidatorToV1(validator),
|
||||
Status: validatorSubStatus(v1Validator, epoch),
|
||||
Validator: v1Validator,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -152,12 +174,71 @@ func valContainersByRequestIds(state iface.BeaconState, validatorIds [][]byte) (
|
||||
}
|
||||
valIndex = types.ValidatorIndex(index)
|
||||
}
|
||||
v1Validator := migration.V1Alpha1ValidatorToV1(allValidators[valIndex])
|
||||
valContainers[i] = ðpb.ValidatorContainer{
|
||||
Index: valIndex,
|
||||
Balance: allBalances[valIndex],
|
||||
Validator: migration.V1Alpha1ValidatorToV1(allValidators[valIndex]),
|
||||
Status: validatorSubStatus(v1Validator, epoch),
|
||||
Validator: v1Validator,
|
||||
}
|
||||
}
|
||||
}
|
||||
return valContainers, nil
|
||||
}
|
||||
|
||||
func validatorStatus(validator *ethpb.Validator, epoch types.Epoch) ethpb.ValidatorStatus {
|
||||
switch validatorSubStatus(validator, epoch) {
|
||||
case ethpb.ValidatorStatus_PENDING_INITIALIZED, ethpb.ValidatorStatus_PENDING_QUEUED:
|
||||
return ethpb.ValidatorStatus_PENDING
|
||||
case ethpb.ValidatorStatus_ACTIVE_ONGOING, ethpb.ValidatorStatus_ACTIVE_SLASHED, ethpb.ValidatorStatus_ACTIVE_EXITING:
|
||||
return ethpb.ValidatorStatus_ACTIVE
|
||||
case ethpb.ValidatorStatus_EXITED_UNSLASHED, ethpb.ValidatorStatus_EXITED_SLASHED:
|
||||
return ethpb.ValidatorStatus_EXITED
|
||||
case ethpb.ValidatorStatus_WITHDRAWAL_POSSIBLE, ethpb.ValidatorStatus_WITHDRAWAL_DONE:
|
||||
return ethpb.ValidatorStatus_WITHDRAWAL
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func validatorSubStatus(validator *ethpb.Validator, epoch types.Epoch) ethpb.ValidatorStatus {
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
|
||||
// Pending.
|
||||
if validator.ActivationEpoch > epoch {
|
||||
if validator.ActivationEligibilityEpoch == farFutureEpoch {
|
||||
return ethpb.ValidatorStatus_PENDING_INITIALIZED
|
||||
} else if validator.ActivationEligibilityEpoch < farFutureEpoch && validator.ActivationEpoch > epoch {
|
||||
return ethpb.ValidatorStatus_PENDING_QUEUED
|
||||
}
|
||||
}
|
||||
|
||||
// Active.
|
||||
if validator.ActivationEpoch <= epoch && epoch < validator.ExitEpoch {
|
||||
if validator.ExitEpoch == farFutureEpoch {
|
||||
return ethpb.ValidatorStatus_ACTIVE_ONGOING
|
||||
} else if validator.ExitEpoch < farFutureEpoch {
|
||||
if validator.Slashed {
|
||||
return ethpb.ValidatorStatus_ACTIVE_SLASHED
|
||||
}
|
||||
return ethpb.ValidatorStatus_ACTIVE_EXITING
|
||||
}
|
||||
}
|
||||
|
||||
// Exited.
|
||||
if validator.ExitEpoch <= epoch && epoch < validator.WithdrawableEpoch {
|
||||
if validator.Slashed {
|
||||
return ethpb.ValidatorStatus_EXITED_SLASHED
|
||||
}
|
||||
return ethpb.ValidatorStatus_EXITED_UNSLASHED
|
||||
}
|
||||
|
||||
if validator.WithdrawableEpoch <= epoch {
|
||||
if validator.EffectiveBalance != 0 {
|
||||
return ethpb.ValidatorStatus_WITHDRAWAL_POSSIBLE
|
||||
} else {
|
||||
return ethpb.ValidatorStatus_WITHDRAWAL_DONE
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ethpb_alpha "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
types "github.com/prysmaticlabs/eth2-types"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1"
|
||||
@@ -112,6 +114,9 @@ func TestListValidators(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(resp.Data), 8192)
|
||||
for _, val := range resp.Data {
|
||||
assert.Equal(t, ethpb.ValidatorStatus_ACTIVE_ONGOING, val.Status)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Head List Validators by index", func(t *testing.T) {
|
||||
@@ -130,6 +135,7 @@ func TestListValidators(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
for i, val := range resp.Data {
|
||||
assert.Equal(t, idNums[i], val.Index)
|
||||
assert.Equal(t, ethpb.ValidatorStatus_ACTIVE_ONGOING, val.Status)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -153,6 +159,7 @@ func TestListValidators(t *testing.T) {
|
||||
for i, val := range resp.Data {
|
||||
assert.Equal(t, idNums[i], val.Index)
|
||||
assert.Equal(t, true, bytes.Equal(pubKeys[i], val.Validator.Pubkey))
|
||||
assert.Equal(t, ethpb.ValidatorStatus_ACTIVE_ONGOING, val.Status)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -178,6 +185,7 @@ func TestListValidators(t *testing.T) {
|
||||
for i, val := range resp.Data {
|
||||
assert.Equal(t, idNums[i], val.Index)
|
||||
assert.Equal(t, true, bytes.Equal(pubkeys[i], val.Validator.Pubkey))
|
||||
assert.Equal(t, ethpb.ValidatorStatus_ACTIVE_ONGOING, val.Status)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -204,6 +212,208 @@ func TestListValidators(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestListValidators_Status(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
var state iface.BeaconState
|
||||
state, _ = testutil.DeterministicGenesisState(t, 8192)
|
||||
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
validators := []*ethpb_alpha.Validator{
|
||||
{
|
||||
ActivationEpoch: farFutureEpoch,
|
||||
ActivationEligibilityEpoch: farFutureEpoch,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: farFutureEpoch,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 0,
|
||||
ExitEpoch: 30,
|
||||
Slashed: true,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
Slashed: false,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
Slashed: true,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
Slashed: false,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
Slashed: false,
|
||||
},
|
||||
{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: 0,
|
||||
Slashed: false,
|
||||
},
|
||||
}
|
||||
for _, validator := range validators {
|
||||
require.NoError(t, state.AppendValidator(validator))
|
||||
require.NoError(t, state.AppendBalance(params.BeaconConfig().MaxEffectiveBalance))
|
||||
}
|
||||
|
||||
t.Run("Head List All ACTIVE Validators", func(t *testing.T) {
|
||||
s := Server{
|
||||
StateFetcher: statefetcher.StateProvider{
|
||||
ChainInfoFetcher: &chainMock.ChainService{State: state},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{
|
||||
StateId: []byte("head"),
|
||||
Status: []ethpb.ValidatorStatus{ethpb.ValidatorStatus_ACTIVE},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(resp.Data), 8192+2 /* 2 active */)
|
||||
for _, datum := range resp.Data {
|
||||
status := validatorStatus(datum.Validator, 0)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
status == ethpb.ValidatorStatus_ACTIVE,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
datum.Status == ethpb.ValidatorStatus_ACTIVE_ONGOING ||
|
||||
datum.Status == ethpb.ValidatorStatus_ACTIVE_EXITING ||
|
||||
datum.Status == ethpb.ValidatorStatus_ACTIVE_SLASHED,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Head List All ACTIVE_ONGOING Validators", func(t *testing.T) {
|
||||
s := Server{
|
||||
StateFetcher: statefetcher.StateProvider{
|
||||
ChainInfoFetcher: &chainMock.ChainService{State: state},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{
|
||||
StateId: []byte("head"),
|
||||
Status: []ethpb.ValidatorStatus{ethpb.ValidatorStatus_ACTIVE_ONGOING},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(resp.Data), 8192+1 /* 1 active_ongoing */)
|
||||
for _, datum := range resp.Data {
|
||||
status := validatorSubStatus(datum.Validator, 0)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
status == ethpb.ValidatorStatus_ACTIVE_ONGOING,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
datum.Status == ethpb.ValidatorStatus_ACTIVE_ONGOING,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch*35))
|
||||
t.Run("Head List All EXITED Validators", func(t *testing.T) {
|
||||
s := Server{
|
||||
StateFetcher: statefetcher.StateProvider{
|
||||
ChainInfoFetcher: &chainMock.ChainService{State: state},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{
|
||||
StateId: []byte("head"),
|
||||
Status: []ethpb.ValidatorStatus{ethpb.ValidatorStatus_EXITED},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4 /* 4 exited */, len(resp.Data))
|
||||
for _, datum := range resp.Data {
|
||||
status := validatorStatus(datum.Validator, 35)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
status == ethpb.ValidatorStatus_EXITED,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
datum.Status == ethpb.ValidatorStatus_EXITED_UNSLASHED || datum.Status == ethpb.ValidatorStatus_EXITED_SLASHED,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Head List All PENDING_INITIALIZED and EXITED_UNSLASHED Validators", func(t *testing.T) {
|
||||
s := Server{
|
||||
StateFetcher: statefetcher.StateProvider{
|
||||
ChainInfoFetcher: &chainMock.ChainService{State: state},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{
|
||||
StateId: []byte("head"),
|
||||
Status: []ethpb.ValidatorStatus{ethpb.ValidatorStatus_PENDING_INITIALIZED, ethpb.ValidatorStatus_EXITED_UNSLASHED},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4 /* 4 exited */, len(resp.Data))
|
||||
for _, datum := range resp.Data {
|
||||
status := validatorSubStatus(datum.Validator, 35)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
status == ethpb.ValidatorStatus_PENDING_INITIALIZED || status == ethpb.ValidatorStatus_EXITED_UNSLASHED,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
datum.Status == ethpb.ValidatorStatus_PENDING_INITIALIZED || datum.Status == ethpb.ValidatorStatus_EXITED_UNSLASHED,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Head List All PENDING and EXITED Validators", func(t *testing.T) {
|
||||
s := Server{
|
||||
StateFetcher: statefetcher.StateProvider{
|
||||
ChainInfoFetcher: &chainMock.ChainService{State: state},
|
||||
},
|
||||
}
|
||||
|
||||
resp, err := s.ListValidators(ctx, ðpb.StateValidatorsRequest{
|
||||
StateId: []byte("head"),
|
||||
Status: []ethpb.ValidatorStatus{ethpb.ValidatorStatus_PENDING, ethpb.ValidatorStatus_EXITED_SLASHED},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2 /* 1 pending, 1 exited */, len(resp.Data))
|
||||
for _, datum := range resp.Data {
|
||||
status := validatorStatus(datum.Validator, 35)
|
||||
subStatus := validatorSubStatus(datum.Validator, 35)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
status == ethpb.ValidatorStatus_PENDING || subStatus == ethpb.ValidatorStatus_EXITED_SLASHED,
|
||||
)
|
||||
require.Equal(
|
||||
t,
|
||||
true,
|
||||
datum.Status == ethpb.ValidatorStatus_PENDING_INITIALIZED || datum.Status == ethpb.ValidatorStatus_EXITED_SLASHED,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
func TestListValidatorBalances(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -431,3 +641,247 @@ func TestListCommittees(t *testing.T) {
|
||||
require.ErrorContains(t, "invalid state ID: foo", err)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_validatorStatus(t *testing.T) {
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
|
||||
type args struct {
|
||||
validator *ethpb.Validator
|
||||
epoch types.Epoch
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want ethpb.ValidatorStatus
|
||||
}{
|
||||
{
|
||||
name: "pending initialized",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: farFutureEpoch,
|
||||
ActivationEligibilityEpoch: farFutureEpoch,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_PENDING,
|
||||
},
|
||||
{
|
||||
name: "active ongoing",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: farFutureEpoch,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_ACTIVE,
|
||||
},
|
||||
{
|
||||
name: "active slashed",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
Slashed: true,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_ACTIVE,
|
||||
},
|
||||
{
|
||||
name: "active exiting",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_ACTIVE,
|
||||
},
|
||||
{
|
||||
name: "exited slashed",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
Slashed: true,
|
||||
},
|
||||
epoch: types.Epoch(35),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_EXITED,
|
||||
},
|
||||
{
|
||||
name: "exited unslashed",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(35),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_EXITED,
|
||||
},
|
||||
{
|
||||
name: "withdrawal possible",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(45),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_WITHDRAWAL,
|
||||
},
|
||||
{
|
||||
name: "withdrawal done",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: 0,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(45),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_WITHDRAWAL,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := validatorStatus(tt.args.validator, tt.args.epoch); got != tt.want {
|
||||
t.Errorf("validatorStatus() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_validatorSubStatus(t *testing.T) {
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
|
||||
type args struct {
|
||||
validator *ethpb.Validator
|
||||
epoch types.Epoch
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want ethpb.ValidatorStatus
|
||||
}{
|
||||
{
|
||||
name: "pending initialized",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: farFutureEpoch,
|
||||
ActivationEligibilityEpoch: farFutureEpoch,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_PENDING_INITIALIZED,
|
||||
},
|
||||
{
|
||||
name: "active ongoing",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: farFutureEpoch,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_ACTIVE_ONGOING,
|
||||
},
|
||||
{
|
||||
name: "active slashed",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
Slashed: true,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_ACTIVE_SLASHED,
|
||||
},
|
||||
{
|
||||
name: "active exiting",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(5),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_ACTIVE_EXITING,
|
||||
},
|
||||
{
|
||||
name: "exited slashed",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
Slashed: true,
|
||||
},
|
||||
epoch: types.Epoch(35),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_EXITED_SLASHED,
|
||||
},
|
||||
{
|
||||
name: "exited unslashed",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(35),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_EXITED_UNSLASHED,
|
||||
},
|
||||
{
|
||||
name: "withdrawal possible",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(45),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_WITHDRAWAL_POSSIBLE,
|
||||
},
|
||||
{
|
||||
name: "withdrawal done",
|
||||
args: args{
|
||||
validator: ðpb.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 30,
|
||||
WithdrawableEpoch: 40,
|
||||
EffectiveBalance: 0,
|
||||
Slashed: false,
|
||||
},
|
||||
epoch: types.Epoch(45),
|
||||
},
|
||||
want: ethpb.ValidatorStatus_WITHDRAWAL_DONE,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := validatorSubStatus(tt.args.validator, tt.args.epoch); got != tt.want {
|
||||
t.Errorf("validatorSubStatus() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user