mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
* Ran gopls modernize to fix everything go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -fix -test ./... * Override rules_go provided dependency for golang.org/x/tools to v0.38.0. To update this, checked out rules_go, then ran `bazel run //go/tools/releaser -- upgrade-dep -mirror=false org_golang_x_tools` and copied the patches. * Fix buildtag violations and ignore buildtag violations in external * Introduce modernize analyzer package. * Add modernize "any" analyzer. * Fix violations of any analyzer * Add modernize "appendclipped" analyzer. * Fix violations of appendclipped * Add modernize "bloop" analyzer. * Add modernize "fmtappendf" analyzer. * Add modernize "forvar" analyzer. * Add modernize "mapsloop" analyzer. * Add modernize "minmax" analyzer. * Fix violations of minmax analyzer * Add modernize "omitzero" analyzer. * Add modernize "rangeint" analyzer. * Fix violations of rangeint. * Add modernize "reflecttypefor" analyzer. * Fix violations of reflecttypefor analyzer. * Add modernize "slicescontains" analyzer. * Add modernize "slicessort" analyzer. * Add modernize "slicesdelete" analyzer. This is disabled by default for now. See https://go.dev/issue/73686. * Add modernize "stringscutprefix" analyzer. * Add modernize "stringsbuilder" analyzer. * Fix violations of stringsbuilder analyzer. * Add modernize "stringsseq" analyzer. * Add modernize "testingcontext" analyzer. * Add modernize "waitgroup" analyzer. * Changelog fragment * gofmt * gazelle * Add modernize "newexpr" analyzer. * Disable newexpr until go1.26 * Add more details in WORKSPACE on how to update the override * @nalepae feedback on min() * gofmt * Fix violations of forvar
252 lines
7.9 KiB
Go
252 lines
7.9 KiB
Go
package simulator
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"math"
|
|
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers"
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
|
"github.com/OffchainLabs/prysm/v7/config/params"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
|
"github.com/OffchainLabs/prysm/v7/crypto/bls"
|
|
"github.com/OffchainLabs/prysm/v7/crypto/rand"
|
|
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
|
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
|
"github.com/OffchainLabs/prysm/v7/runtime/version"
|
|
"github.com/OffchainLabs/prysm/v7/time/slots"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (s *Simulator) generateAttestationsForSlot(ctx context.Context, ver int, slot primitives.Slot) ([]ethpb.IndexedAtt, []ethpb.AttSlashing, error) {
|
|
attestations := make([]ethpb.IndexedAtt, 0)
|
|
slashings := make([]ethpb.AttSlashing, 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 := min(i+valsPerAttestation, endIdx)
|
|
indices := make([]uint64, 0, valsPerAttestation)
|
|
for idx := i; idx < attEndIdx; idx++ {
|
|
indices = append(indices, idx)
|
|
}
|
|
|
|
var att ethpb.IndexedAtt
|
|
if ver >= version.Electra {
|
|
att = ðpb.IndexedAttestationElectra{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
} else {
|
|
att = ðpb.IndexedAttestation{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|
|
|
|
beaconState, err := s.srvConfig.AttestationStateFetcher.AttestationTargetState(ctx, att.GetData().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
|
|
}
|
|
|
|
if ver >= version.Electra {
|
|
att.(*ethpb.IndexedAttestationElectra).Signature = aggSig.Marshal()
|
|
} else {
|
|
att.(*ethpb.IndexedAttestation).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
|
|
}
|
|
|
|
if ver >= version.Electra {
|
|
slashableAtt.(*ethpb.IndexedAttestationElectra).Signature = aggSig.Marshal()
|
|
} else {
|
|
slashableAtt.(*ethpb.IndexedAttestation).Signature = aggSig.Marshal()
|
|
}
|
|
|
|
slashedIndices = append(slashedIndices, slashableAtt.GetAttestingIndices()...)
|
|
|
|
attDataRoot, err := att.GetData().HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, errors.Wrap(err, "cannot compte `att` hash tree root")
|
|
}
|
|
|
|
slashableAttDataRoot, err := slashableAtt.GetData().HashTreeRoot()
|
|
if err != nil {
|
|
return nil, nil, errors.Wrap(err, "cannot compte `slashableAtt` hash tree root")
|
|
}
|
|
|
|
var slashing ethpb.AttSlashing
|
|
if ver >= version.Electra {
|
|
slashing = ðpb.AttesterSlashingElectra{
|
|
Attestation_1: att.(*ethpb.IndexedAttestationElectra),
|
|
Attestation_2: slashableAtt.(*ethpb.IndexedAttestationElectra),
|
|
}
|
|
} else {
|
|
slashing = ðpb.AttesterSlashing{
|
|
Attestation_1: att.(*ethpb.IndexedAttestation),
|
|
Attestation_2: slashableAtt.(*ethpb.IndexedAttestation),
|
|
}
|
|
}
|
|
|
|
// Ensure the attestation with the lower data root is the first attestation.
|
|
if bytes.Compare(attDataRoot[:], slashableAttDataRoot[:]) > 0 {
|
|
if ver >= version.Electra {
|
|
slashing = ðpb.AttesterSlashingElectra{
|
|
Attestation_1: slashableAtt.(*ethpb.IndexedAttestationElectra),
|
|
Attestation_2: att.(*ethpb.IndexedAttestationElectra),
|
|
}
|
|
} else {
|
|
slashing = ðpb.AttesterSlashing{
|
|
Attestation_1: slashableAtt.(*ethpb.IndexedAttestation),
|
|
Attestation_2: att.(*ethpb.IndexedAttestation),
|
|
}
|
|
}
|
|
}
|
|
|
|
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.IndexedAtt,
|
|
) (bls.Signature, error) {
|
|
domain, err := signing.Domain(
|
|
beaconState.Fork(),
|
|
att.GetData().Target.Epoch,
|
|
params.BeaconConfig().DomainBeaconAttester,
|
|
beaconState.GenesisValidatorsRoot(),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signingRoot, err := signing.ComputeSigningRoot(att.GetData(), domain)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sigs := make([]bls.Signature, len(att.GetAttestingIndices()))
|
|
for i, validatorIndex := range att.GetAttestingIndices() {
|
|
privKey := s.srvConfig.PrivateKeysByValidatorIndex[primitives.ValidatorIndex(validatorIndex)]
|
|
sigs[i] = privKey.Sign(signingRoot[:])
|
|
}
|
|
return bls.AggregateSignatures(sigs), nil
|
|
}
|
|
|
|
func makeSlashableFromAtt(att ethpb.IndexedAtt, indices []uint64) ethpb.IndexedAtt {
|
|
if att.GetData().Source.Epoch <= 2 {
|
|
return makeDoubleVoteFromAtt(att, indices)
|
|
}
|
|
attData := ðpb.AttestationData{
|
|
Slot: att.GetData().Slot,
|
|
CommitteeIndex: att.GetData().CommitteeIndex,
|
|
BeaconBlockRoot: att.GetData().BeaconBlockRoot,
|
|
Source: ðpb.Checkpoint{
|
|
Epoch: att.GetData().Source.Epoch - 3,
|
|
Root: att.GetData().Source.Root,
|
|
},
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: att.GetData().Target.Epoch,
|
|
Root: att.GetData().Target.Root,
|
|
},
|
|
}
|
|
|
|
if att.Version() >= version.Electra {
|
|
return ðpb.IndexedAttestationElectra{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|
|
|
|
return ðpb.IndexedAttestation{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|
|
|
|
func makeDoubleVoteFromAtt(att ethpb.IndexedAtt, indices []uint64) ethpb.IndexedAtt {
|
|
attData := ðpb.AttestationData{
|
|
Slot: att.GetData().Slot,
|
|
CommitteeIndex: att.GetData().CommitteeIndex,
|
|
BeaconBlockRoot: bytesutil.PadTo([]byte("slash me"), 32),
|
|
Source: ðpb.Checkpoint{
|
|
Epoch: att.GetData().Source.Epoch,
|
|
Root: att.GetData().Source.Root,
|
|
},
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: att.GetData().Target.Epoch,
|
|
Root: att.GetData().Target.Root,
|
|
},
|
|
}
|
|
|
|
if att.Version() >= version.Electra {
|
|
return ðpb.IndexedAttestationElectra{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|
|
|
|
return ðpb.IndexedAttestation{
|
|
AttestingIndices: indices,
|
|
Data: attData,
|
|
Signature: params.BeaconConfig().EmptySignature[:],
|
|
}
|
|
}
|