mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-05 09:14:28 +00:00
af203efa0c
* `helpers.go`: Improve naming consistency. * `detect_attestations.go`: Improve readability. * `receive.go`: Add `attsQueueSize` in log message. * `checkSlashableAttestations`: Improve logging. `avgBatchProcessingTime` is not displayed any more if not batch is processed. * `loadChunks`: Use explicit `chunkKind` and `chunkIndices`. * `getChunk`: Use specific `chunkIndex` and `chunkKind`. * `validatorIndicesInChunk` -> `validatorIndexesInChunk`. * `epochUpdateForValidator`: Use explicit arguments. * `getChunk`: Change order of arguments. * `latestEpochWrittenForValidator`: Use `ok` parameter. So the default value is not any more considered as the absence of value. * `applyAttestationForValidator`: Use explicit arguments. * `updateSpans`: Use explicit arguments. * `saveUpdatedChunks`: Use explicit arguments. * `checkSurrounds`: Use explicit arguments. We see here that, previously, in `checkSlashableAttestations`, `checkSurrounds` was called with the default value of `slashertypes`: `MinSpan`. Now, we set it expliciterly at `MinSpan`, which may explicit a bug. * `epochUpdateForValidator`: Set modified by the function argument first. * `applyAttestationForValidator`: Set mutated argument `chunksByChunkIdx`first. * `applyAttestationForValidator`: Rename variables. * `Test_processQueuedAttestations`: Fix test. Two tests were actually exactly the same. * `updateSpans`: Keep happy path in the outer scope. Even if in this case the "happy" path means slashing. * `checkSurrounds`: Rename variable. * `getChunk`: Avoid side effects. It adds a few lines for callers, but it does not modify any more arguments and it does what it says: getting a chunk. * `CheckSlashable`: Flatten. * `detect_attestations_test.go`: Simplify. * `CheckSlashable`: Add error log in case of missing attestation. * `processQueuedAttestations`: Extract a sub function. So testing will be easier. * `processAttesterSlashings` and `processProposerSlashings`: Improve. * `processAttesterSlashings`: Return processed slashings. * `createAttestationWrapper`: Rename variables. * `signingRoot` ==> `headerRoot` or `dataRoot`. Before this commit, there is two typse of `signing root`s floating around. - The first one is a real signing root, aka a hash tree root computed from an object root and a domain. This real signing root is the object ready to be signed. - The second one is a "false" signing root, which is actually just the hash tree root of an object. This object is either the `Data` field of an attestation, or the `Header` field of a block. Having 2 differents objects with the same name `signing root` is quite confusing. This commit renames wrongly named `signing root` objects. * `createAttestationWrapper` => `createAttestationWrapperEmptySig`. So it's clear for the user that the created attestation wrapper has an empty signature. * Implement `createAttestationWrapper`. * `processAttestations`: Return processed attester slashings. * Test `processAttestations` instead of `processQueuedAttestations`. By testing `processAttestations` instead of `processQueuedAttestations`, we get rid of a lot of tests fixtures, including the 200 ms sleep. The whole testing duration is shorter. * `Test_processAttestations`: Allow multiple steps. * `Test_processAttestations`: Add double steps tests. Some new failing tests are commented with a corresponding github issue. * `NextChunkStartEpoch`: Fix function comment. Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com> * `chunks.go`: Avoid templating log messages. * `checkSlashableAttestations`: Simplify duration computation. --------- Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
82 lines
3.1 KiB
Go
82 lines
3.1 KiB
Go
package slasher
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/pkg/errors"
|
|
slashertypes "github.com/prysmaticlabs/prysm/v4/beacon-chain/slasher/types"
|
|
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
|
"go.opencensus.io/trace"
|
|
)
|
|
|
|
// detectProposerSlashings takes in signed block header wrappers and returns a list of proposer slashings detected.
|
|
func (s *Service) detectProposerSlashings(
|
|
ctx context.Context,
|
|
incomingProposals []*slashertypes.SignedBlockHeaderWrapper,
|
|
) ([]*ethpb.ProposerSlashing, error) {
|
|
ctx, span := trace.StartSpan(ctx, "slasher.detectProposerSlashings")
|
|
defer span.End()
|
|
|
|
// internalSlashings will contain any slashable double proposals in the input list
|
|
// of proposals with respect to each other.
|
|
internalSlashings := []*ethpb.ProposerSlashing{}
|
|
|
|
existingProposals := make(map[string]*slashertypes.SignedBlockHeaderWrapper)
|
|
|
|
// We check if there are any slashable double proposals in the input list
|
|
// of proposals with respect to each other.
|
|
for _, incomingProposal := range incomingProposals {
|
|
key := proposalKey(incomingProposal)
|
|
existingProposal, ok := existingProposals[key]
|
|
|
|
// If we have not seen this proposal before, we add it to our map of existing proposals
|
|
// and we continue to the next proposal.
|
|
if !ok {
|
|
existingProposals[key] = incomingProposal
|
|
continue
|
|
}
|
|
|
|
// If we have seen this proposal before, we check if it is a double proposal.
|
|
if isDoubleProposal(incomingProposal.HeaderRoot, existingProposal.HeaderRoot) {
|
|
doubleProposalsTotal.Inc()
|
|
|
|
slashing := ðpb.ProposerSlashing{
|
|
Header_1: existingProposal.SignedBeaconBlockHeader,
|
|
Header_2: incomingProposal.SignedBeaconBlockHeader,
|
|
}
|
|
|
|
internalSlashings = append(internalSlashings, slashing)
|
|
}
|
|
}
|
|
|
|
// We check if there are any slashable double proposals in the input list
|
|
// of proposals with respect to the slasher database.
|
|
databaseSlashings, err := s.serviceCfg.Database.CheckDoubleBlockProposals(ctx, incomingProposals)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not check for double proposals on disk")
|
|
}
|
|
|
|
// We save the safe proposals (with respect to the database) to our database.
|
|
// If some proposals in incomingProposals are slashable with respect to each other,
|
|
// we (arbitrarily) save the last one to the database.
|
|
if err := s.serviceCfg.Database.SaveBlockProposals(ctx, incomingProposals); err != nil {
|
|
return nil, errors.Wrap(err, "could not save safe proposals")
|
|
}
|
|
|
|
// totalSlashings contain all slashings we have detected.
|
|
totalSlashings := append(internalSlashings, databaseSlashings...)
|
|
return totalSlashings, nil
|
|
}
|
|
|
|
// proposalKey build a key which is a combination of the slot and the proposer index.
|
|
// If a validator proposes several blocks for the same slot, then several (potentially slashable)
|
|
// proposals will correspond to the same key.
|
|
func proposalKey(proposal *slashertypes.SignedBlockHeaderWrapper) string {
|
|
header := proposal.SignedBeaconBlockHeader.Header
|
|
|
|
slotKey := uintToString(uint64(header.Slot))
|
|
proposerIndexKey := uintToString(uint64(header.ProposerIndex))
|
|
|
|
return slotKey + ":" + proposerIndexKey
|
|
}
|