Restrict Proposer Lookup to the Current Epoch (#7542)

* checkpoint

* add test

* Update beacon-chain/core/helpers/committee_test.go

* preston's review

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
Nishant Das 2020-10-27 04:40:38 +08:00 committed by GitHub
parent ec77196197
commit f1bce1001d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 3 deletions

View File

@ -186,7 +186,9 @@ func CommitteeAssignments(
return nil, nil, err
}
proposerIndexToSlots := make(map[uint64][]uint64, params.BeaconConfig().SlotsPerEpoch)
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
// Proposal epochs do not have a look ahead, so we skip them over here.
validProposalEpoch := epoch < nextEpoch
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch && validProposalEpoch; slot++ {
// Skip proposer assignment for genesis slot.
if slot == 0 {
continue

View File

@ -203,6 +203,36 @@ func TestCommitteeAssignments_CanRetrieve(t *testing.T) {
}
}
func TestCommitteeAssignments_CannotRetrieveFuture(t *testing.T) {
// Initialize test with 256 validators, each slot and each index gets 4 validators.
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)
for i := 0; i < len(validators); i++ {
// First 2 epochs only half validators are activated.
var activationEpoch uint64
if i >= len(validators)/2 {
activationEpoch = 3
}
validators[i] = &ethpb.Validator{
ActivationEpoch: activationEpoch,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 2 * params.BeaconConfig().SlotsPerEpoch, // epoch 2
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
})
require.NoError(t, err)
_, proposerIndxs, err := CommitteeAssignments(state, CurrentEpoch(state))
require.NoError(t, err)
require.NotEqual(t, 0, len(proposerIndxs), "wanted non-zero proposer index set")
_, proposerIndxs, err = CommitteeAssignments(state, CurrentEpoch(state)+1)
require.NoError(t, err)
require.Equal(t, 0, len(proposerIndxs), "wanted empty proposer index set")
}
func TestCommitteeAssignments_EverySlotHasMin1Proposer(t *testing.T) {
// Initialize test with 256 validators, each slot and each index gets 4 validators.
validators := make([]*ethpb.Validator, 4*params.BeaconConfig().SlotsPerEpoch)

View File

@ -275,6 +275,39 @@ func TestBeaconProposerIndex_OK(t *testing.T) {
}
}
func TestBeaconProposerIndex_BadState(t *testing.T) {
params.SetupTestConfigCleanup(t)
ClearCache()
c := params.BeaconConfig()
c.MinGenesisActiveValidatorCount = 16384
params.OverrideBeaconConfig(c)
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount/8)
for i := 0; i < len(validators); i++ {
validators[i] = &ethpb.Validator{
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
}
}
roots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot)
for i := uint64(0); i < params.BeaconConfig().SlotsPerHistoricalRoot; i++ {
roots[i] = make([]byte, 32)
}
state, err := beaconstate.InitializeFromProto(&pb.BeaconState{
Validators: validators,
Slot: 0,
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
BlockRoots: roots,
StateRoots: roots,
})
require.NoError(t, err)
// Set a very high slot, so that retrieved block root will be
// non existent for the proposer cache.
require.NoError(t, state.SetSlot(100))
_, err = BeaconProposerIndex(state)
require.NoError(t, err)
assert.Equal(t, 0, len(proposerIndicesCache.ProposerIndicesCache.ListKeys()))
}
func TestComputeProposerIndex_Compatibility(t *testing.T) {
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
for i := 0; i < len(validators); i++ {

View File

@ -128,7 +128,7 @@ func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.
return nil, status.Errorf(codes.Internal, "Could not compute committee assignments: %v", err)
}
// Query the next epoch assignments for committee subnet subscriptions.
nextCommitteeAssignments, nextProposerIndexToSlots, err := helpers.CommitteeAssignments(s, req.Epoch+1)
nextCommitteeAssignments, _, err := helpers.CommitteeAssignments(s, req.Epoch+1)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not compute next committee assignments: %v", err)
}
@ -153,9 +153,9 @@ func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.
assignment.Status = assignmentStatus(s, idx)
assignment.ProposerSlots = proposerIndexToSlots[idx]
// The next epoch has no lookup for proposer indexes.
nextAssignment.ValidatorIndex = idx
nextAssignment.Status = assignmentStatus(s, idx)
nextAssignment.ProposerSlots = nextProposerIndexToSlots[idx]
ca, ok := committeeAssignments[idx]
if ok {