mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
5a66807989
* First take at updating everything to v5 * Patch gRPC gateway to use prysm v5 Fix patch * Update go ssz --------- Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
201 lines
6.3 KiB
Go
201 lines
6.3 KiB
Go
package simulator
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"math"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
|
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
|
"github.com/prysmaticlabs/prysm/v5/crypto/rand"
|
|
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
|
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (s *Simulator) generateAttestationsForSlot(
|
|
ctx context.Context, slot primitives.Slot,
|
|
) ([]*ethpb.IndexedAttestation, []*ethpb.AttesterSlashing, error) {
|
|
attestations := make([]*ethpb.IndexedAttestation, 0)
|
|
slashings := make([]*ethpb.AttesterSlashing, 0)
|
|
currentEpoch := slots.ToEpoch(slot)
|
|
|
|
committeesPerSlot := helpers.SlotCommitteeCount(s.srvConfig.Params.NumValidators)
|
|
valsPerCommittee := s.srvConfig.Params.NumValidators /
|
|
(committeesPerSlot * uint64(s.srvConfig.Params.SlotsPerEpoch))
|
|
valsPerSlot := committeesPerSlot * valsPerCommittee
|
|
|
|
if currentEpoch < 2 {
|
|
return nil, nil, nil
|
|
}
|
|
sourceEpoch := currentEpoch - 1
|
|
|
|
var slashedIndices []uint64
|
|
startIdx := valsPerSlot * uint64(slot%s.srvConfig.Params.SlotsPerEpoch)
|
|
endIdx := startIdx + valsPerCommittee
|
|
for c := primitives.CommitteeIndex(0); uint64(c) < committeesPerSlot; c++ {
|
|
attData := ðpb.AttestationData{
|
|
Slot: slot,
|
|
CommitteeIndex: c,
|
|
BeaconBlockRoot: bytesutil.PadTo([]byte("block"), 32),
|
|
Source: ðpb.Checkpoint{
|
|
Epoch: sourceEpoch,
|
|
Root: bytesutil.PadTo([]byte("source"), 32),
|
|
},
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: currentEpoch,
|
|
Root: bytesutil.PadTo([]byte("target"), 32),
|
|
},
|
|
}
|
|
|
|
valsPerAttestation := uint64(math.Floor(s.srvConfig.Params.AggregationPercent * float64(valsPerCommittee)))
|
|
for i := startIdx; i < endIdx; i += valsPerAttestation {
|
|
attEndIdx := i + valsPerAttestation
|
|
if attEndIdx >= endIdx {
|
|
attEndIdx = endIdx
|
|
}
|
|
indices := make([]uint64, 0, valsPerAttestation)
|
|
for idx := i; idx < attEndIdx; idx++ {
|
|
indices = append(indices, idx)
|
|
}
|
|
att := ðpb.IndexedAttestation{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
beaconState, err := s.srvConfig.AttestationStateFetcher.AttestationTargetState(ctx, att.Data.Target)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// Sign the attestation with a valid signature.
|
|
aggSig, err := s.aggregateSigForAttestation(beaconState, att)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
att.Signature = aggSig.Marshal()
|
|
|
|
attestations = append(attestations, att)
|
|
if rand.NewGenerator().Float64() < s.srvConfig.Params.AttesterSlashingProbab {
|
|
slashableAtt := makeSlashableFromAtt(att, []uint64{indices[0]})
|
|
aggSig, err := s.aggregateSigForAttestation(beaconState, slashableAtt)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
slashableAtt.Signature = aggSig.Marshal()
|
|
slashedIndices = append(slashedIndices, slashableAtt.AttestingIndices...)
|
|
|
|
attDataRoot, err := att.Data.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, errors.Wrap(err, "cannot compte `att` hash tree root")
|
|
}
|
|
|
|
slashableAttDataRoot, err := slashableAtt.Data.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, errors.Wrap(err, "cannot compte `slashableAtt` hash tree root")
|
|
}
|
|
|
|
slashing := ðpb.AttesterSlashing{
|
|
Attestation_1: att,
|
|
Attestation_2: slashableAtt,
|
|
}
|
|
|
|
// Ensure the attestation with the lower data root is the first attestation.
|
|
if bytes.Compare(attDataRoot[:], slashableAttDataRoot[:]) > 0 {
|
|
slashing = ðpb.AttesterSlashing{
|
|
Attestation_1: slashableAtt,
|
|
Attestation_2: att,
|
|
}
|
|
}
|
|
|
|
slashings = append(slashings, slashing)
|
|
attestations = append(attestations, slashableAtt)
|
|
}
|
|
}
|
|
startIdx += valsPerCommittee
|
|
endIdx += valsPerCommittee
|
|
}
|
|
if len(slashedIndices) > 0 {
|
|
log.WithFields(logrus.Fields{
|
|
"amount": len(slashedIndices),
|
|
"indices": slashedIndices,
|
|
}).Infof("Slashable attestation made")
|
|
}
|
|
return attestations, slashings, nil
|
|
}
|
|
|
|
func (s *Simulator) aggregateSigForAttestation(
|
|
beaconState state.ReadOnlyBeaconState, att *ethpb.IndexedAttestation,
|
|
) (bls.Signature, error) {
|
|
domain, err := signing.Domain(
|
|
beaconState.Fork(),
|
|
att.Data.Target.Epoch,
|
|
params.BeaconConfig().DomainBeaconAttester,
|
|
beaconState.GenesisValidatorsRoot(),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signingRoot, err := signing.ComputeSigningRoot(att.Data, domain)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sigs := make([]bls.Signature, len(att.AttestingIndices))
|
|
for i, validatorIndex := range att.AttestingIndices {
|
|
privKey := s.srvConfig.PrivateKeysByValidatorIndex[primitives.ValidatorIndex(validatorIndex)]
|
|
sigs[i] = privKey.Sign(signingRoot[:])
|
|
}
|
|
return bls.AggregateSignatures(sigs), nil
|
|
}
|
|
|
|
func makeSlashableFromAtt(att *ethpb.IndexedAttestation, indices []uint64) *ethpb.IndexedAttestation {
|
|
if att.Data.Source.Epoch <= 2 {
|
|
return makeDoubleVoteFromAtt(att, indices)
|
|
}
|
|
attData := ðpb.AttestationData{
|
|
Slot: att.Data.Slot,
|
|
CommitteeIndex: att.Data.CommitteeIndex,
|
|
BeaconBlockRoot: att.Data.BeaconBlockRoot,
|
|
Source: ðpb.Checkpoint{
|
|
Epoch: att.Data.Source.Epoch - 3,
|
|
Root: att.Data.Source.Root,
|
|
},
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: att.Data.Target.Epoch,
|
|
Root: att.Data.Target.Root,
|
|
},
|
|
}
|
|
return ðpb.IndexedAttestation{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|
|
|
|
func makeDoubleVoteFromAtt(att *ethpb.IndexedAttestation, indices []uint64) *ethpb.IndexedAttestation {
|
|
attData := ðpb.AttestationData{
|
|
Slot: att.Data.Slot,
|
|
CommitteeIndex: att.Data.CommitteeIndex,
|
|
BeaconBlockRoot: bytesutil.PadTo([]byte("slash me"), 32),
|
|
Source: ðpb.Checkpoint{
|
|
Epoch: att.Data.Source.Epoch,
|
|
Root: att.Data.Source.Root,
|
|
},
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: att.Data.Target.Epoch,
|
|
Root: att.Data.Target.Root,
|
|
},
|
|
}
|
|
return ðpb.IndexedAttestation{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|