mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-04 00:44:27 +00:00
87 lines
3.6 KiB
Go
87 lines
3.6 KiB
Go
|
package blocks
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
|
||
|
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
||
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||
|
"github.com/prysmaticlabs/prysm/shared/params"
|
||
|
)
|
||
|
|
||
|
// ProcessProposerSlashings is one of the operations performed
|
||
|
// on each processed beacon block to penalize proposers based on
|
||
|
// slashing conditions if any slashable events occurred.
|
||
|
//
|
||
|
// Official spec definition for proposer slashins:
|
||
|
// Verify that len(block.body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS.
|
||
|
//
|
||
|
// For each proposer_slashing in block.body.proposer_slashings:
|
||
|
//
|
||
|
// Let proposer = state.validator_registry[proposer_slashing.proposer_index].
|
||
|
// Verify that bls_verify(pubkey=proposer.pubkey, msg=hash_tree_root(
|
||
|
// proposer_slashing.proposal_data_1),
|
||
|
// sig=proposer_slashing.proposal_signature_1,
|
||
|
// domain=get_domain(state.fork_data, proposer_slashing.proposal_data_1.slot, DOMAIN_PROPOSAL)).
|
||
|
// Verify that bls_verify(pubkey=proposer.pubkey, msg=hash_tree_root(
|
||
|
// proposer_slashing.proposal_data_2),
|
||
|
// sig=proposer_slashing.proposal_signature_2,
|
||
|
// domain=get_domain(state.fork_data, proposer_slashing.proposal_data_2.slot, DOMAIN_PROPOSAL)).
|
||
|
// Verify that proposer_slashing.proposal_data_1.slot == proposer_slashing.proposal_data_2.slot.
|
||
|
// Verify that proposer_slashing.proposal_data_1.shard == proposer_slashing.proposal_data_2.shard.
|
||
|
// Verify that proposer_slashing.proposal_data_1.block_root != proposer_slashing.proposal_data_2.block_root.
|
||
|
// Verify that proposer.status != EXITED_WITH_PENALTY.
|
||
|
// Run update_validator_status(state, proposer_slashing.proposer_index, new_status=EXITED_WITH_PENALTY).
|
||
|
func ProcessProposerSlashings(
|
||
|
validatorRegistry []*pb.ValidatorRecord,
|
||
|
proposerSlashings []*pb.ProposerSlashing,
|
||
|
currentSlot uint64,
|
||
|
) ([]*pb.ValidatorRecord, error) {
|
||
|
if uint64(len(proposerSlashings)) > params.BeaconConfig().MaxProposerSlashings {
|
||
|
return nil, fmt.Errorf(
|
||
|
"number of proposer slashings (%d) exceeds allowed threshold of %d",
|
||
|
len(proposerSlashings),
|
||
|
params.BeaconConfig().MaxProposerSlashings,
|
||
|
)
|
||
|
}
|
||
|
for idx, slashing := range proposerSlashings {
|
||
|
if err := verifyProposerSlashing(slashing); err != nil {
|
||
|
return nil, fmt.Errorf("could not verify proposer slashing #%d: %v", idx, err)
|
||
|
}
|
||
|
proposer := validatorRegistry[slashing.GetProposerIndex()]
|
||
|
if proposer.Status != pb.ValidatorRecord_EXITED_WITH_PENALTY {
|
||
|
// TODO(#781): Replace with
|
||
|
// update_validator_status(
|
||
|
// state,
|
||
|
// proposer_slashing.proposer_index,
|
||
|
// new_status=EXITED_WITH_PENALTY,
|
||
|
// ) after update_validator_status is implemented.
|
||
|
validatorRegistry[slashing.GetProposerIndex()] = v.ExitValidator(proposer, currentSlot, true /* penalize */)
|
||
|
}
|
||
|
}
|
||
|
return validatorRegistry, nil
|
||
|
}
|
||
|
|
||
|
func verifyProposerSlashing(
|
||
|
slashing *pb.ProposerSlashing,
|
||
|
) error {
|
||
|
// TODO(#781): Verify BLS according to the specification in the "Proposer Slashings"
|
||
|
// section of block operations.
|
||
|
slot1 := slashing.GetProposalData_1().GetSlot()
|
||
|
slot2 := slashing.GetProposalData_2().GetSlot()
|
||
|
shard1 := slashing.GetProposalData_1().GetShard()
|
||
|
shard2 := slashing.GetProposalData_2().GetShard()
|
||
|
root1 := slashing.GetProposalData_1().GetBlockRoot()
|
||
|
root2 := slashing.GetProposalData_2().GetBlockRoot()
|
||
|
if slot1 != slot2 {
|
||
|
return fmt.Errorf("slashing proposal data slots do not match: %d, %d", slot1, slot2)
|
||
|
}
|
||
|
if shard1 != shard2 {
|
||
|
return fmt.Errorf("slashing proposal data shards do not match: %d, %d", shard1, shard2)
|
||
|
}
|
||
|
if !bytes.Equal(root1, root2) {
|
||
|
return fmt.Errorf("slashing proposal data block roots do not match: %#x, %#x", root1, root2)
|
||
|
}
|
||
|
return nil
|
||
|
}
|