mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-03 09:37:38 +00:00
125 lines
3.8 KiB
Go
125 lines
3.8 KiB
Go
package forkchoice
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/Giulio2002/bls"
|
|
"github.com/ledgerwatch/erigon/cl/cltypes/solid"
|
|
"github.com/ledgerwatch/erigon/cl/fork"
|
|
"github.com/ledgerwatch/erigon/cl/phase1/core/state"
|
|
"github.com/ledgerwatch/erigon/cl/pool"
|
|
|
|
"github.com/ledgerwatch/erigon/cl/cltypes"
|
|
)
|
|
|
|
func (f *ForkChoiceStore) OnAttesterSlashing(attesterSlashing *cltypes.AttesterSlashing, test bool) error {
|
|
if f.operationsPool.AttesterSlashingsPool.Has(pool.ComputeKeyForAttesterSlashing(attesterSlashing)) {
|
|
return nil
|
|
}
|
|
f.mu.Lock()
|
|
// Check if this attestation is even slashable.
|
|
attestation1 := attesterSlashing.Attestation_1
|
|
attestation2 := attesterSlashing.Attestation_2
|
|
if !cltypes.IsSlashableAttestationData(attestation1.Data, attestation2.Data) {
|
|
f.mu.Unlock()
|
|
return fmt.Errorf("attestation data is not slashable")
|
|
}
|
|
// Retrieve justified state
|
|
s, err := f.forkGraph.GetState(f.justifiedCheckpoint.BlockRoot(), false)
|
|
if err != nil {
|
|
f.mu.Unlock()
|
|
return err
|
|
}
|
|
if s == nil {
|
|
f.mu.Unlock()
|
|
return fmt.Errorf("justified checkpoint state not accessible")
|
|
}
|
|
attestation1PublicKeys, err := getIndexedAttestationPublicKeys(s, attestation1)
|
|
if err != nil {
|
|
f.mu.Unlock()
|
|
return err
|
|
}
|
|
attestation2PublicKeys, err := getIndexedAttestationPublicKeys(s, attestation2)
|
|
if err != nil {
|
|
f.mu.Unlock()
|
|
return err
|
|
}
|
|
domain1, err := s.GetDomain(s.BeaconConfig().DomainBeaconAttester, attestation1.Data.Target().Epoch())
|
|
if err != nil {
|
|
return fmt.Errorf("unable to get the domain: %v", err)
|
|
}
|
|
domain2, err := s.GetDomain(s.BeaconConfig().DomainBeaconAttester, attestation2.Data.Target().Epoch())
|
|
if err != nil {
|
|
return fmt.Errorf("unable to get the domain: %v", err)
|
|
}
|
|
f.mu.Unlock()
|
|
|
|
if !test {
|
|
// Verify validity of slashings (1)
|
|
signingRoot, err := fork.ComputeSigningRoot(attestation1.Data, domain1)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to get signing root: %v", err)
|
|
}
|
|
|
|
valid, err := bls.VerifyAggregate(attestation1.Signature[:], signingRoot[:], attestation1PublicKeys)
|
|
if err != nil {
|
|
return fmt.Errorf("error while validating signature: %v", err)
|
|
}
|
|
if !valid {
|
|
return fmt.Errorf("invalid aggregate signature")
|
|
}
|
|
// Verify validity of slashings (2)
|
|
signingRoot, err = fork.ComputeSigningRoot(attestation2.Data, domain2)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to get signing root: %v", err)
|
|
}
|
|
|
|
valid, err = bls.VerifyAggregate(attestation2.Signature[:], signingRoot[:], attestation2PublicKeys)
|
|
if err != nil {
|
|
return fmt.Errorf("error while validating signature: %v", err)
|
|
}
|
|
if !valid {
|
|
return fmt.Errorf("invalid aggregate signature")
|
|
}
|
|
}
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
var anySlashed bool
|
|
for _, index := range solid.IntersectionOfSortedSets(attestation1.AttestingIndices, attestation2.AttestingIndices) {
|
|
f.equivocatingIndicies[index] = struct{}{}
|
|
if !anySlashed {
|
|
v, err := s.ValidatorForValidatorIndex(int(index))
|
|
if err != nil {
|
|
return fmt.Errorf("unable to retrieve state: %v", err)
|
|
}
|
|
if v.IsSlashable(state.Epoch(s)) {
|
|
anySlashed = true
|
|
}
|
|
}
|
|
}
|
|
if anySlashed {
|
|
f.operationsPool.AttesterSlashingsPool.Insert(pool.ComputeKeyForAttesterSlashing(attesterSlashing), attesterSlashing)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func getIndexedAttestationPublicKeys(b *state.CachingBeaconState, att *cltypes.IndexedAttestation) ([][]byte, error) {
|
|
inds := att.AttestingIndices
|
|
if inds.Length() == 0 || !solid.IsUint64SortedSet(inds) {
|
|
return nil, fmt.Errorf("isValidIndexedAttestation: attesting indices are not sorted or are null")
|
|
}
|
|
pks := make([][]byte, 0, inds.Length())
|
|
if err := solid.RangeErr[uint64](inds, func(_ int, v uint64, _ int) error {
|
|
val, err := b.ValidatorForValidatorIndex(int(v))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pk := val.PublicKey()
|
|
pks = append(pks, pk[:])
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
return pks, nil
|
|
}
|