-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This implements a helper to get the ptc committee from a state. It uses the cached beacon committees if possible It also implements a helper to compute the largest power of two of a uint64 and a helper to test for nil payload attestation messages
- Loading branch information
Showing
6 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package helpers | ||
|
||
var ( | ||
ErrNilMessage = errNilMessage | ||
ErrNilData = errNilData | ||
ErrNilBeaconBlockRoot = errNilBeaconBlockRoot | ||
ErrNilPayloadAttestation = errNilPayloadAttestation | ||
ErrNilSignature = errNilSignature | ||
ErrNilAggregationBits = errNilAggregationBits | ||
ErrPreEPBSState = errPreEPBSState | ||
ErrCommitteeOverflow = errCommitteeOverflow | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package helpers | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state" | ||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" | ||
"github.com/prysmaticlabs/prysm/v5/math" | ||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" | ||
"github.com/prysmaticlabs/prysm/v5/runtime/version" | ||
"github.com/prysmaticlabs/prysm/v5/time/slots" | ||
) | ||
|
||
var ( | ||
errNilMessage = errors.New("nil PayloadAttestationMessage") | ||
errNilData = errors.New("nil PayloadAttestationData") | ||
errNilBeaconBlockRoot = errors.New("nil BeaconBlockRoot") | ||
errNilPayloadAttestation = errors.New("nil PayloadAttestation") | ||
errNilSignature = errors.New("nil Signature") | ||
errNilAggregationBits = errors.New("nil AggregationBits") | ||
errPreEPBSState = errors.New("beacon state pre ePBS fork") | ||
errCommitteeOverflow = errors.New("beacon committee of insufficient size") | ||
) | ||
|
||
// ValidateNilPayloadAttestationData checks if any composite field of the | ||
// payload attestation data is nil | ||
func ValidateNilPayloadAttestationData(data *eth.PayloadAttestationData) error { | ||
if data == nil { | ||
return errNilData | ||
} | ||
if data.BeaconBlockRoot == nil { | ||
return errNilBeaconBlockRoot | ||
} | ||
return nil | ||
} | ||
|
||
// ValidateNilPayloadAttestationMessage checks if any composite field of the | ||
// payload attestation message is nil | ||
func ValidateNilPayloadAttestationMessage(att *eth.PayloadAttestationMessage) error { | ||
if att == nil { | ||
return errNilMessage | ||
} | ||
if att.Signature == nil { | ||
return errNilSignature | ||
} | ||
return ValidateNilPayloadAttestationData(att.Data) | ||
} | ||
|
||
// ValidateNilPayloadAttestation checks if any composite field of the | ||
// payload attestation is nil | ||
func ValidateNilPayloadAttestation(att *eth.PayloadAttestation) error { | ||
if att == nil { | ||
return errNilPayloadAttestation | ||
} | ||
if att.AggregationBits == nil { | ||
return errNilAggregationBits | ||
} | ||
if att.Signature == nil { | ||
return errNilSignature | ||
} | ||
return ValidateNilPayloadAttestationData(att.Data) | ||
} | ||
|
||
// GetPayloadTimelinessCommittee returns the PTC for the given slot, computed from the passed state as in the | ||
// spec function `get_ptc`. | ||
func GetPayloadTimelinessCommittee(ctx context.Context, state state.ReadOnlyBeaconState, slot primitives.Slot) (indices []primitives.ValidatorIndex, err error) { | ||
if state.Version() < version.EPBS { | ||
return nil, errPreEPBSState | ||
} | ||
epoch := slots.ToEpoch(slot) | ||
activeCount, err := ActiveValidatorCount(ctx, state, epoch) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "could not compute active validator count") | ||
} | ||
committeesPerSlot := math.LargestPowerOfTwo(math.Min(SlotCommitteeCount(activeCount), fieldparams.PTCSize)) | ||
membersPerCommittee := fieldparams.PTCSize / committeesPerSlot | ||
for i := uint64(0); i <= committeesPerSlot; i++ { | ||
committee, err := BeaconCommitteeFromState(ctx, state, slot, primitives.CommitteeIndex(i)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if uint64(len(committee)) < membersPerCommittee { | ||
return nil, errCommitteeOverflow | ||
} | ||
start := uint64(len(committee)) - membersPerCommittee | ||
indices = append(indices, committee[start:]...) | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package helpers_test | ||
|
||
import ( | ||
"context" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/go-bitfield" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers" | ||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native" | ||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams" | ||
"github.com/prysmaticlabs/prysm/v5/config/params" | ||
"github.com/prysmaticlabs/prysm/v5/math" | ||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" | ||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1" | ||
"github.com/prysmaticlabs/prysm/v5/testing/require" | ||
"github.com/prysmaticlabs/prysm/v5/testing/util/random" | ||
"github.com/prysmaticlabs/prysm/v5/time/slots" | ||
) | ||
|
||
func TestValidateNilPayloadAttestation(t *testing.T) { | ||
require.ErrorIs(t, helpers.ErrNilData, helpers.ValidateNilPayloadAttestationData(nil)) | ||
data := ð.PayloadAttestationData{} | ||
require.ErrorIs(t, helpers.ErrNilBeaconBlockRoot, helpers.ValidateNilPayloadAttestationData(data)) | ||
data.BeaconBlockRoot = make([]byte, 32) | ||
require.NoError(t, helpers.ValidateNilPayloadAttestationData(data)) | ||
|
||
require.ErrorIs(t, helpers.ErrNilMessage, helpers.ValidateNilPayloadAttestationMessage(nil)) | ||
message := ð.PayloadAttestationMessage{} | ||
require.ErrorIs(t, helpers.ErrNilSignature, helpers.ValidateNilPayloadAttestationMessage(message)) | ||
message.Signature = make([]byte, 96) | ||
require.ErrorIs(t, helpers.ErrNilData, helpers.ValidateNilPayloadAttestationMessage(message)) | ||
message.Data = data | ||
require.NoError(t, helpers.ValidateNilPayloadAttestationMessage(message)) | ||
|
||
require.ErrorIs(t, helpers.ErrNilPayloadAttestation, helpers.ValidateNilPayloadAttestation(nil)) | ||
att := ð.PayloadAttestation{} | ||
require.ErrorIs(t, helpers.ErrNilAggregationBits, helpers.ValidateNilPayloadAttestation(att)) | ||
att.AggregationBits = bitfield.NewBitvector512() | ||
require.ErrorIs(t, helpers.ErrNilSignature, helpers.ValidateNilPayloadAttestation(att)) | ||
att.Signature = message.Signature | ||
require.ErrorIs(t, helpers.ErrNilData, helpers.ValidateNilPayloadAttestation(att)) | ||
att.Data = data | ||
require.NoError(t, helpers.ValidateNilPayloadAttestation(att)) | ||
} | ||
|
||
func TestGetPayloadTimelinessCommittee(t *testing.T) { | ||
helpers.ClearCache() | ||
|
||
// Create 10 committees | ||
committeeCount := uint64(10) | ||
validatorCount := committeeCount * params.BeaconConfig().TargetCommitteeSize * uint64(params.BeaconConfig().SlotsPerEpoch) | ||
validators := make([]*ethpb.Validator, validatorCount) | ||
|
||
for i := 0; i < len(validators); i++ { | ||
k := make([]byte, 48) | ||
copy(k, strconv.Itoa(i)) | ||
validators[i] = ðpb.Validator{ | ||
PublicKey: k, | ||
WithdrawalCredentials: make([]byte, 32), | ||
ExitEpoch: params.BeaconConfig().FarFutureEpoch, | ||
} | ||
} | ||
|
||
state, err := state_native.InitializeFromProtoEpbs(random.BeaconState(t)) | ||
require.NoError(t, err) | ||
require.NoError(t, state.SetValidators(validators)) | ||
require.NoError(t, state.SetSlot(200)) | ||
|
||
ctx := context.Background() | ||
indices, err := helpers.BeaconCommitteeFromState(ctx, state, state.Slot(), 1) | ||
require.NoError(t, err) | ||
require.Equal(t, 128, len(indices)) | ||
|
||
epoch := slots.ToEpoch(state.Slot()) | ||
activeCount, err := helpers.ActiveValidatorCount(ctx, state, epoch) | ||
require.NoError(t, err) | ||
require.Equal(t, uint64(40960), activeCount) | ||
|
||
computedCommitteeCount := helpers.SlotCommitteeCount(activeCount) | ||
require.Equal(t, committeeCount, computedCommitteeCount) | ||
committeesPerSlot := math.LargestPowerOfTwo(math.Min(committeeCount, fieldparams.PTCSize)) | ||
require.Equal(t, uint64(8), committeesPerSlot) | ||
|
||
ptc, err := helpers.GetPayloadTimelinessCommittee(ctx, state, state.Slot()) | ||
require.NoError(t, err) | ||
|
||
committee1, err := helpers.BeaconCommitteeFromState(ctx, state, state.Slot(), 0) | ||
require.NoError(t, err) | ||
|
||
require.DeepEqual(t, committee1[len(committee1)-64:], ptc[:64]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters