mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 21:07:18 +00:00
9edba29f64
* slashing simulator * add in necessary items for slasher sim * sim item * fix up * fixed build * rev * slasher sim in testing * testonly * gaz * gaz * fix viz Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: prestonvanloon <preston@prysmaticlabs.com>
178 lines
5.6 KiB
Go
178 lines
5.6 KiB
Go
package simulator
|
|
|
|
import (
|
|
"context"
|
|
"math"
|
|
|
|
types "github.com/prysmaticlabs/eth2-types"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/signing"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/config/params"
|
|
"github.com/prysmaticlabs/prysm/crypto/bls"
|
|
"github.com/prysmaticlabs/prysm/crypto/rand"
|
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (s *Simulator) generateAttestationsForSlot(
|
|
ctx context.Context, slot types.Slot,
|
|
) ([]*ethpb.IndexedAttestation, []*ethpb.AttesterSlashing, error) {
|
|
attestations := make([]*ethpb.IndexedAttestation, 0)
|
|
slashings := make([]*ethpb.AttesterSlashing, 0)
|
|
currentEpoch := core.SlotToEpoch(slot)
|
|
|
|
committeesPerSlot := helpers.SlotCommitteeCount(s.srvConfig.Params.NumValidators)
|
|
valsPerCommittee := s.srvConfig.Params.NumValidators /
|
|
(committeesPerSlot * uint64(s.srvConfig.Params.SlotsPerEpoch))
|
|
valsPerSlot := committeesPerSlot * valsPerCommittee
|
|
|
|
var sourceEpoch types.Epoch = 0
|
|
if currentEpoch != 0 {
|
|
sourceEpoch = currentEpoch - 1
|
|
}
|
|
|
|
var slashedIndices []uint64
|
|
startIdx := valsPerSlot * uint64(slot%s.srvConfig.Params.SlotsPerEpoch)
|
|
endIdx := startIdx + valsPerCommittee
|
|
for c := types.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...)
|
|
slashings = append(slashings, ðpb.AttesterSlashing{
|
|
Attestation_1: att,
|
|
Attestation_2: slashableAtt,
|
|
})
|
|
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.BeaconState, att *ethpb.IndexedAttestation,
|
|
) (bls.Signature, error) {
|
|
domain, err := signing.Domain(
|
|
beaconState.Fork(),
|
|
att.Data.Target.Epoch,
|
|
params.BeaconConfig().DomainBeaconAttester,
|
|
beaconState.GenesisValidatorRoot(),
|
|
)
|
|
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[types.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[:],
|
|
}
|
|
}
|