mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-23 20:07:17 +00:00
d17996f8b0
* Update V3 from V4 * Fix build v3 -> v4 * Update ssz * Update beacon_chain.pb.go * Fix formatter import * Update update-mockgen.sh comment to v4 * Fix conflicts. Pass build and tests * Fix test
230 lines
7.8 KiB
Go
230 lines
7.8 KiB
Go
package blocks
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/signing"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/time"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/primitives"
|
|
"github.com/prysmaticlabs/prysm/v4/crypto/bls"
|
|
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/attestation"
|
|
"go.opencensus.io/trace"
|
|
)
|
|
|
|
// ProcessAttestationsNoVerifySignature applies processing operations to a block's inner attestation
|
|
// records. The only difference would be that the attestation signature would not be verified.
|
|
func ProcessAttestationsNoVerifySignature(
|
|
ctx context.Context,
|
|
beaconState state.BeaconState,
|
|
b interfaces.ReadOnlySignedBeaconBlock,
|
|
) (state.BeaconState, error) {
|
|
if err := blocks.BeaconBlockIsNil(b); err != nil {
|
|
return nil, err
|
|
}
|
|
body := b.Block().Body()
|
|
var err error
|
|
for idx, att := range body.Attestations() {
|
|
beaconState, err = ProcessAttestationNoVerifySignature(ctx, beaconState, att)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "could not verify attestation at index %d in block", idx)
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
// VerifyAttestationNoVerifySignature verifies the attestation without verifying the attestation signature. This is
|
|
// used before processing attestation with the beacon state.
|
|
func VerifyAttestationNoVerifySignature(
|
|
ctx context.Context,
|
|
beaconState state.ReadOnlyBeaconState,
|
|
att *ethpb.Attestation,
|
|
) error {
|
|
ctx, span := trace.StartSpan(ctx, "core.VerifyAttestationNoVerifySignature")
|
|
defer span.End()
|
|
|
|
if err := helpers.ValidateNilAttestation(att); err != nil {
|
|
return err
|
|
}
|
|
currEpoch := time.CurrentEpoch(beaconState)
|
|
prevEpoch := time.PrevEpoch(beaconState)
|
|
data := att.Data
|
|
if data.Target.Epoch != prevEpoch && data.Target.Epoch != currEpoch {
|
|
return fmt.Errorf(
|
|
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
|
|
data.Target.Epoch,
|
|
prevEpoch,
|
|
currEpoch,
|
|
)
|
|
}
|
|
|
|
if data.Target.Epoch == currEpoch {
|
|
if !beaconState.MatchCurrentJustifiedCheckpoint(data.Source) {
|
|
return errors.New("source check point not equal to current justified checkpoint")
|
|
}
|
|
} else {
|
|
if !beaconState.MatchPreviousJustifiedCheckpoint(data.Source) {
|
|
return errors.New("source check point not equal to previous justified checkpoint")
|
|
}
|
|
}
|
|
|
|
if err := helpers.ValidateSlotTargetEpoch(att.Data); err != nil {
|
|
return err
|
|
}
|
|
|
|
s := att.Data.Slot
|
|
minInclusionCheck := s+params.BeaconConfig().MinAttestationInclusionDelay <= beaconState.Slot()
|
|
epochInclusionCheck := beaconState.Slot() <= s+params.BeaconConfig().SlotsPerEpoch
|
|
if !minInclusionCheck {
|
|
return fmt.Errorf(
|
|
"attestation slot %d + inclusion delay %d > state slot %d",
|
|
s,
|
|
params.BeaconConfig().MinAttestationInclusionDelay,
|
|
beaconState.Slot(),
|
|
)
|
|
}
|
|
if !epochInclusionCheck {
|
|
return fmt.Errorf(
|
|
"state slot %d > attestation slot %d + SLOTS_PER_EPOCH %d",
|
|
beaconState.Slot(),
|
|
s,
|
|
params.BeaconConfig().SlotsPerEpoch,
|
|
)
|
|
}
|
|
activeValidatorCount, err := helpers.ActiveValidatorCount(ctx, beaconState, att.Data.Target.Epoch)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c := helpers.SlotCommitteeCount(activeValidatorCount)
|
|
if uint64(att.Data.CommitteeIndex) >= c {
|
|
return fmt.Errorf("committee index %d >= committee count %d", att.Data.CommitteeIndex, c)
|
|
}
|
|
|
|
if err := helpers.VerifyAttestationBitfieldLengths(ctx, beaconState, att); err != nil {
|
|
return errors.Wrap(err, "could not verify attestation bitfields")
|
|
}
|
|
|
|
// Verify attesting indices are correct.
|
|
committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
indexedAtt, err := attestation.ConvertToIndexed(ctx, att, committee)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return attestation.IsValidAttestationIndices(ctx, indexedAtt)
|
|
}
|
|
|
|
// ProcessAttestationNoVerifySignature processes the attestation without verifying the attestation signature. This
|
|
// method is used to validate attestations whose signatures have already been verified.
|
|
func ProcessAttestationNoVerifySignature(
|
|
ctx context.Context,
|
|
beaconState state.BeaconState,
|
|
att *ethpb.Attestation,
|
|
) (state.BeaconState, error) {
|
|
ctx, span := trace.StartSpan(ctx, "core.ProcessAttestationNoVerifySignature")
|
|
defer span.End()
|
|
|
|
if err := VerifyAttestationNoVerifySignature(ctx, beaconState, att); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
currEpoch := time.CurrentEpoch(beaconState)
|
|
data := att.Data
|
|
s := att.Data.Slot
|
|
proposerIndex, err := helpers.BeaconProposerIndex(ctx, beaconState)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pendingAtt := ðpb.PendingAttestation{
|
|
Data: data,
|
|
AggregationBits: att.AggregationBits,
|
|
InclusionDelay: beaconState.Slot() - s,
|
|
ProposerIndex: proposerIndex,
|
|
}
|
|
|
|
if data.Target.Epoch == currEpoch {
|
|
if err := beaconState.AppendCurrentEpochAttestations(pendingAtt); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := beaconState.AppendPreviousEpochAttestations(pendingAtt); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return beaconState, nil
|
|
}
|
|
|
|
// VerifyAttestationSignature converts and attestation into an indexed attestation and verifies
|
|
// the signature in that attestation.
|
|
func VerifyAttestationSignature(ctx context.Context, beaconState state.ReadOnlyBeaconState, att *ethpb.Attestation) error {
|
|
if err := helpers.ValidateNilAttestation(att); err != nil {
|
|
return err
|
|
}
|
|
committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
indexedAtt, err := attestation.ConvertToIndexed(ctx, att, committee)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return VerifyIndexedAttestation(ctx, beaconState, indexedAtt)
|
|
}
|
|
|
|
// VerifyIndexedAttestation determines the validity of an indexed attestation.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
|
|
// """
|
|
// Check if ``indexed_attestation`` is not empty, has sorted and unique indices and has a valid aggregate signature.
|
|
// """
|
|
// # Verify indices are sorted and unique
|
|
// indices = indexed_attestation.attesting_indices
|
|
// if len(indices) == 0 or not indices == sorted(set(indices)):
|
|
// return False
|
|
// # Verify aggregate signature
|
|
// pubkeys = [state.validators[i].pubkey for i in indices]
|
|
// domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
|
|
// signing_root = compute_signing_root(indexed_attestation.data, domain)
|
|
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
|
|
func VerifyIndexedAttestation(ctx context.Context, beaconState state.ReadOnlyBeaconState, indexedAtt *ethpb.IndexedAttestation) error {
|
|
ctx, span := trace.StartSpan(ctx, "core.VerifyIndexedAttestation")
|
|
defer span.End()
|
|
|
|
if err := attestation.IsValidAttestationIndices(ctx, indexedAtt); err != nil {
|
|
return err
|
|
}
|
|
domain, err := signing.Domain(
|
|
beaconState.Fork(),
|
|
indexedAtt.Data.Target.Epoch,
|
|
params.BeaconConfig().DomainBeaconAttester,
|
|
beaconState.GenesisValidatorsRoot(),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
indices := indexedAtt.AttestingIndices
|
|
var pubkeys []bls.PublicKey
|
|
for i := 0; i < len(indices); i++ {
|
|
pubkeyAtIdx := beaconState.PubkeyAtIndex(primitives.ValidatorIndex(indices[i]))
|
|
pk, err := bls.PublicKeyFromBytes(pubkeyAtIdx[:])
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not deserialize validator public key")
|
|
}
|
|
pubkeys = append(pubkeys, pk)
|
|
}
|
|
return attestation.VerifyIndexedAttestationSig(ctx, indexedAtt, pubkeys, domain)
|
|
}
|