diff --git a/beacon-chain/core/helpers/BUILD.bazel b/beacon-chain/core/helpers/BUILD.bazel index 70f753e264e..4ff959b4806 100644 --- a/beacon-chain/core/helpers/BUILD.bazel +++ b/beacon-chain/core/helpers/BUILD.bazel @@ -21,6 +21,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//beacon-chain/cache:go_default_library", + "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/forkchoice/types:go_default_library", "//beacon-chain/state:go_default_library", @@ -73,6 +74,7 @@ go_test( tags = ["CI_race_detection"], deps = [ "//beacon-chain/cache:go_default_library", + "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/time:go_default_library", "//beacon-chain/forkchoice/types:go_default_library", "//beacon-chain/state:go_default_library", @@ -82,7 +84,9 @@ go_test( "//consensus-types/epbs:go_default_library", "//consensus-types/primitives:go_default_library", "//container/slice:go_default_library", + "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", + "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//proto/prysm/v1alpha1:go_default_library", diff --git a/beacon-chain/core/helpers/beacon_committee.go b/beacon-chain/core/helpers/beacon_committee.go index 43da4b4a5b3..a0cb67dcba8 100644 --- a/beacon-chain/core/helpers/beacon_committee.go +++ b/beacon-chain/core/helpers/beacon_committee.go @@ -295,7 +295,7 @@ func CommitteeAssignments(ctx context.Context, state state.BeaconState, epoch pr if err := verifyAssignmentEpoch(epoch, state); err != nil { return nil, err } - startSlot, err := slots.EpochStart(epoch) + slot, err := slots.EpochStart(epoch) if err != nil { return nil, err } @@ -305,20 +305,16 @@ func CommitteeAssignments(ctx context.Context, state state.BeaconState, epoch pr } assignments := make(map[primitives.ValidatorIndex]*CommitteeAssignment) - activeValidatorCount, err := ActiveValidatorCount(ctx, state, epoch) + committees, err := BeaconCommittees(ctx, state, slot) if err != nil { - return nil, err + return nil, errors.Wrap(err, "could not compute beacon committees") } - ptcPerSlot, PtcMembersPerCommittee := PtcAllocation(activeValidatorCount) - + ptcPerSlot, ptcMembersPerCommittee := PtcAllocation(len(committees)) // Compute committee assignments for each slot in the epoch. - for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ { - committees, err := BeaconCommittees(ctx, state, slot) - if err != nil { - return nil, errors.Wrap(err, "could not compute beacon committees") - } + endSlot := slot + params.BeaconConfig().SlotsPerEpoch + for { for j, committee := range committees { - for _, vIndex := range committee { + for i, vIndex := range committee { if _, ok := vals[vIndex]; !ok { // Skip if the validator is not in the provided validators slice. continue } @@ -328,48 +324,21 @@ func CommitteeAssignments(ctx context.Context, state state.BeaconState, epoch pr assignments[vIndex].Committee = committee assignments[vIndex].AttesterSlot = slot assignments[vIndex].CommitteeIndex = primitives.CommitteeIndex(j) - } - - // We only need to assign PTC slots for the first `PTCPerSlot` committees of a given slot. - if uint64(j) < ptcPerSlot { - assignments = PTCAssignments(committee, assignments, PtcMembersPerCommittee, slot) + if uint64(j) < ptcPerSlot && uint64(i) < ptcMembersPerCommittee { + assignments[vIndex].PtcSlot = slot + } } } - } - return assignments, nil -} - -// PTCAssignments updates the PTC slot assignments for the given committee members. -// committee: a slice of ValidatorIndex representing committee members. -// assignments: a map of ValidatorIndex to CommitteeAssignment where assignments will be updated. -// membersPerCommittee: the number of members to be assigned to the PTC committee. -// slot: the slot to be assigned for PTC assignment. -// Returns the updated assignments map. -func PTCAssignments(committee []primitives.ValidatorIndex, - assignments map[primitives.ValidatorIndex]*CommitteeAssignment, - membersPerCommittee uint64, - slot primitives.Slot) map[primitives.ValidatorIndex]*CommitteeAssignment { - committeeLength := uint64(len(committee)) - // If the number of PTC members is greater than Beacon members, - // return the current assignments without changes. - if membersPerCommittee > committeeLength { - return assignments - } - - // Loop through the selected committee members for PTC assignments. - for i := uint64(0); i < membersPerCommittee; i++ { - vIndex := committee[i] - - assignment, exists := assignments[vIndex] - if !exists { - assignment = &CommitteeAssignment{} - assignments[vIndex] = assignment + slot++ + if slot == endSlot { + break + } + committees, err = BeaconCommittees(ctx, state, slot) + if err != nil { + return nil, errors.Wrap(err, "could not compute beacon committees") } - - assignment.PtcSlot = slot } - - return assignments + return assignments, nil } // VerifyBitfieldLength verifies that a bitfield length matches the given committee size. diff --git a/beacon-chain/core/helpers/payload_attestation.go b/beacon-chain/core/helpers/payload_attestation.go index 2342ac5a2fd..348c419f8f6 100644 --- a/beacon-chain/core/helpers/payload_attestation.go +++ b/beacon-chain/core/helpers/payload_attestation.go @@ -74,16 +74,14 @@ func GetPayloadTimelinessCommittee(ctx context.Context, state state.ReadOnlyBeac if state.Version() < version.EPBS { return nil, errPreEPBSState } - epoch := slots.ToEpoch(slot) - activeCount, err := ActiveValidatorCount(ctx, state, epoch) + committees, err := BeaconCommittees(ctx, state, slot) if err != nil { - return nil, errors.Wrap(err, "could not compute active validator count") + return nil, errors.Wrap(err, "could not get beacon committees") } - committeesPerSlot, membersPerCommittee := PtcAllocation(activeCount) - for i := uint64(0); i < committeesPerSlot; i++ { - committee, err := BeaconCommitteeFromState(ctx, state, slot, primitives.CommitteeIndex(i)) - if err != nil { - return nil, err + committeesPerSlot, membersPerCommittee := PtcAllocation(len(committees)) + for i, committee := range committees { + if uint64(i) >= committeesPerSlot { + return } if uint64(len(committee)) < membersPerCommittee { return nil, errCommitteeOverflow @@ -96,9 +94,8 @@ func GetPayloadTimelinessCommittee(ctx context.Context, state state.ReadOnlyBeac // PtcAllocation returns: // 1. The number of beacon committees that PTC will borrow from in a slot. // 2. The number of validators that PTC will borrow from in a beacon committee. -func PtcAllocation(totalActive uint64) (committeesPerSlot, membersPerCommittee uint64) { - slotCommittees := SlotCommitteeCount(totalActive) - committeesPerSlot = math.LargestPowerOfTwo(math.Min(slotCommittees, fieldparams.PTCSize)) +func PtcAllocation(slotCommittees int) (committeesPerSlot, membersPerCommittee uint64) { + committeesPerSlot = math.LargestPowerOfTwo(math.Min(uint64(slotCommittees), fieldparams.PTCSize)) membersPerCommittee = fieldparams.PTCSize / committeesPerSlot return } diff --git a/beacon-chain/core/helpers/payload_attestation_test.go b/beacon-chain/core/helpers/payload_attestation_test.go index a613fd136ad..d65da5c5c13 100644 --- a/beacon-chain/core/helpers/payload_attestation_test.go +++ b/beacon-chain/core/helpers/payload_attestation_test.go @@ -101,24 +101,24 @@ func TestGetPayloadTimelinessCommittee(t *testing.T) { func Test_PtcAllocation(t *testing.T) { tests := []struct { - totalActive uint64 + committeeCount int memberPerCommittee uint64 committeesPerSlot uint64 }{ - {64, 512, 1}, - {params.BeaconConfig().MinGenesisActiveValidatorCount, 128, 4}, - {25600, 128, 4}, - {256000, 16, 32}, - {1024000, 8, 64}, + {1, 512, 1}, + {4, 128, 4}, + {128, 4, 128}, + {512, 1, 512}, + {1024, 1, 512}, } for _, test := range tests { - committeesPerSlot, memberPerCommittee := helpers.PtcAllocation(test.totalActive) + committeesPerSlot, memberPerCommittee := helpers.PtcAllocation(test.committeeCount) if memberPerCommittee != test.memberPerCommittee { - t.Errorf("memberPerCommittee(%d) = %d; expected %d", test.totalActive, memberPerCommittee, test.memberPerCommittee) + t.Errorf("memberPerCommittee(%d) = %d; expected %d", test.committeeCount, memberPerCommittee, test.memberPerCommittee) } if committeesPerSlot != test.committeesPerSlot { - t.Errorf("committeesPerSlot(%d) = %d; expected %d", test.totalActive, committeesPerSlot, test.committeesPerSlot) + t.Errorf("committeesPerSlot(%d) = %d; expected %d", test.committeeCount, committeesPerSlot, test.committeesPerSlot) } } }