mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-05-02 03:02:54 -04:00
Ensure exits are not for an already exited validator (#4701)
* ensure exits are not for an already exited validator
This commit is contained in:
@@ -10,6 +10,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
],
|
||||
@@ -21,6 +22,8 @@ go_test(
|
||||
srcs = ["service_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/state:go_default_library",
|
||||
"//proto/beacon/p2p/v1:go_default_library",
|
||||
"//shared/params:go_default_library",
|
||||
"@com_github_gogo_protobuf//proto:go_default_library",
|
||||
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -29,7 +30,7 @@ func NewPool() *Pool {
|
||||
|
||||
// PendingExits returns exits that are ready for inclusion at the given slot. This method will not
|
||||
// return more than the block enforced MaxVoluntaryExits.
|
||||
func (p *Pool) PendingExits(slot uint64) []*ethpb.SignedVoluntaryExit {
|
||||
func (p *Pool) PendingExits(state *beaconstate.BeaconState, slot uint64) []*ethpb.SignedVoluntaryExit {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
pending := make([]*ethpb.SignedVoluntaryExit, 0)
|
||||
@@ -37,7 +38,9 @@ func (p *Pool) PendingExits(slot uint64) []*ethpb.SignedVoluntaryExit {
|
||||
if e.Exit.Epoch > helpers.SlotToEpoch(slot) {
|
||||
continue
|
||||
}
|
||||
pending = append(pending, e)
|
||||
if v, err := state.ValidatorAtIndexReadOnly(e.Exit.ValidatorIndex); err == nil && v.ExitEpoch() == params.BeaconConfig().FarFutureEpoch {
|
||||
pending = append(pending, e)
|
||||
}
|
||||
}
|
||||
if len(pending) > int(params.BeaconConfig().MaxVoluntaryExits) {
|
||||
pending = pending[:params.BeaconConfig().MaxVoluntaryExits]
|
||||
@@ -47,7 +50,7 @@ func (p *Pool) PendingExits(slot uint64) []*ethpb.SignedVoluntaryExit {
|
||||
|
||||
// InsertVoluntaryExit into the pool. This method is a no-op if the pending exit already exists,
|
||||
// has been included recently, or the validator is already exited.
|
||||
func (p *Pool) InsertVoluntaryExit(ctx context.Context, validators []*ethpb.Validator, exit *ethpb.SignedVoluntaryExit) {
|
||||
func (p *Pool) InsertVoluntaryExit(ctx context.Context, state *beaconstate.BeaconState, exit *ethpb.SignedVoluntaryExit) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
@@ -57,7 +60,7 @@ func (p *Pool) InsertVoluntaryExit(ctx context.Context, validators []*ethpb.Vali
|
||||
}
|
||||
|
||||
// Has the validator been exited already?
|
||||
if len(validators) <= int(exit.Exit.ValidatorIndex) || validators[exit.Exit.ValidatorIndex].ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
if v, err := state.ValidatorAtIndexReadOnly(exit.Exit.ValidatorIndex); err != nil || v.ExitEpoch() != params.BeaconConfig().FarFutureEpoch {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
beaconstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||
p2ppb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
)
|
||||
|
||||
@@ -211,7 +213,11 @@ func TestPool_InsertVoluntaryExit(t *testing.T) {
|
||||
pending: tt.fields.pending,
|
||||
included: tt.fields.included,
|
||||
}
|
||||
p.InsertVoluntaryExit(ctx, validators, tt.args.exit)
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(&p2ppb.BeaconState{Validators: validators})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p.InsertVoluntaryExit(ctx, s, tt.args.exit)
|
||||
if len(p.pending) != len(tt.want) {
|
||||
t.Fatalf("Mismatched lengths of pending list. Got %d, wanted %d.", len(p.pending), len(tt.want))
|
||||
}
|
||||
@@ -444,7 +450,11 @@ func TestPool_PendingExits(t *testing.T) {
|
||||
p := &Pool{
|
||||
pending: tt.fields.pending,
|
||||
}
|
||||
if got := p.PendingExits(tt.args.slot); !reflect.DeepEqual(got, tt.want) {
|
||||
s, err := beaconstate.InitializeFromProtoUnsafe(&p2ppb.BeaconState{Validators: []*ethpb.Validator{{ExitEpoch: params.BeaconConfig().FarFutureEpoch}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := p.PendingExits(s, tt.args.slot); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("PendingExits() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -40,7 +40,7 @@ func (vs *Server) ProposeExit(ctx context.Context, req *ethpb.SignedVoluntaryExi
|
||||
},
|
||||
})
|
||||
|
||||
vs.ExitPool.InsertVoluntaryExit(ctx, s.Validators(), req)
|
||||
vs.ExitPool.InsertVoluntaryExit(ctx, s, req)
|
||||
|
||||
return &ptypes.Empty{}, vs.P2P.Broadcast(ctx, req)
|
||||
}
|
||||
|
||||
@@ -63,6 +63,11 @@ func (vs *Server) GetBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb
|
||||
|
||||
graffiti := bytesutil.ToBytes32(req.Graffiti)
|
||||
|
||||
head, err := vs.HeadFetcher.HeadState(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not get head state %v", err)
|
||||
}
|
||||
|
||||
blk := ðpb.BeaconBlock{
|
||||
Slot: req.Slot,
|
||||
ParentRoot: parentRoot[:],
|
||||
@@ -75,7 +80,7 @@ func (vs *Server) GetBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb
|
||||
// TODO(2766): Implement rest of the retrievals for beacon block operations
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{},
|
||||
AttesterSlashings: []*ethpb.AttesterSlashing{},
|
||||
VoluntaryExits: vs.ExitPool.PendingExits(req.Slot),
|
||||
VoluntaryExits: vs.ExitPool.PendingExits(head, req.Slot),
|
||||
Graffiti: graffiti[:],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ func (r *Service) voluntaryExitSubscriber(ctx context.Context, msg proto.Message
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.exitPool.InsertVoluntaryExit(ctx, s.Validators(), msg.(*ethpb.SignedVoluntaryExit))
|
||||
r.exitPool.InsertVoluntaryExit(ctx, s, msg.(*ethpb.SignedVoluntaryExit))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user