-
Notifications
You must be signed in to change notification settings - Fork 962
/
slashing_helper.go
128 lines (109 loc) · 3.94 KB
/
slashing_helper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package evaluators
import (
"context"
"crypto/rand"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
"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/encoding/bytesutil"
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/util"
"google.golang.org/protobuf/types/known/emptypb"
)
type doubleAttestationHelper struct {
valClient eth.BeaconNodeValidatorClient
beaconClient eth.BeaconChainClient
privKeys []bls.SecretKey
pubKeys [][]byte
domainResp *eth.DomainResponse
attData *eth.AttestationData
committee []primitives.ValidatorIndex
}
// Initializes helper with details needed to make a double attestation for testint purposes
// Populates the committee of that is responsible for the
func (h *doubleAttestationHelper) setup(ctx context.Context) error {
chainHead, err := h.beaconClient.GetChainHead(ctx, &emptypb.Empty{})
if err != nil {
return errors.Wrap(err, "could not get chain head")
}
_, privKeys, err := util.DeterministicDepositsAndKeys(params.BeaconConfig().MinGenesisActiveValidatorCount)
if err != nil {
return errors.Wrap(err, "could not get depositsandkeys")
}
pubKeys := make([][]byte, len(privKeys))
for i, priv := range privKeys {
pubKeys[i] = priv.PublicKey().Marshal()
}
duties, err := h.valClient.GetDuties(ctx, ð.DutiesRequest{
Epoch: chainHead.HeadEpoch,
PublicKeys: pubKeys,
})
if err != nil {
return errors.Wrap(err, "could not get duties")
}
var committeeIndex primitives.CommitteeIndex
var committee []primitives.ValidatorIndex
for _, duty := range duties.CurrentEpochDuties {
if duty.AttesterSlot == chainHead.HeadSlot {
committeeIndex = duty.CommitteeIndex
committee = duty.Committee
break
}
}
attDataReq := ð.AttestationDataRequest{
CommitteeIndex: committeeIndex,
Slot: chainHead.HeadSlot,
}
attData, err := h.valClient.GetAttestationData(ctx, attDataReq)
if err != nil {
return err
}
req := ð.DomainRequest{
Epoch: chainHead.HeadEpoch,
Domain: params.BeaconConfig().DomainBeaconAttester[:],
}
domainResp, err := h.valClient.DomainData(ctx, req)
if err != nil {
return errors.Wrap(err, "could not get domain data")
}
h.privKeys = privKeys
h.pubKeys = pubKeys
h.domainResp = domainResp
h.committee = committee
h.attData = attData
return nil
}
// Returns the validatorIndex at index idx of the fetched committee in setup()
func (h *doubleAttestationHelper) validatorIndexAtCommitteeIndex(idx uint64) primitives.ValidatorIndex {
return h.committee[idx]
}
// Returns a attestation was previously submitted, at the previous slot, modifying it so that it is signed
// by the validator indicated by idx. idx represents the index in the committee of the attestation.
// The block root value is random, which allows this to be seen by P2P networks as
// new, unique blocks.
func (h *doubleAttestationHelper) getSlashableAttestation(idx uint64) (*eth.Attestation, error) {
// msg must be unique so they are not filtered by P2P
randVal := make([]byte, 4)
_, err := rand.Read(randVal)
if err != nil {
return nil, errors.Wrap(err, "error reading random val")
}
blockRoot := bytesutil.ToBytes32(append(randVal, []byte("muahahahaha evil validator")...))
h.attData.BeaconBlockRoot = blockRoot[:]
signingRoot, err := signing.ComputeSigningRoot(h.attData, h.domainResp.SignatureDomain)
if err != nil {
return nil, errors.Wrap(err, "could not get chain head")
}
valIdx := h.validatorIndexAtCommitteeIndex(idx)
attBitfield := bitfield.NewBitlist(uint64(len(h.committee)))
attBitfield.SetBitAt(idx, true)
att := ð.Attestation{
AggregationBits: attBitfield,
Data: h.attData,
Signature: h.privKeys[valIdx].Sign(signingRoot[:]).Marshal(),
}
return att, nil
}