github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/blocks/proposer_slashing.go (about) 1 package blocks 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/pkg/errors" 8 types "github.com/prysmaticlabs/eth2-types" 9 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 10 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 11 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 12 "github.com/prysmaticlabs/prysm/shared/params" 13 "google.golang.org/protobuf/proto" 14 ) 15 16 type slashValidatorFunc func(iface.BeaconState, types.ValidatorIndex) (iface.BeaconState, error) 17 18 // ProcessProposerSlashings is one of the operations performed 19 // on each processed beacon block to slash proposers based on 20 // slashing conditions if any slashable events occurred. 21 // 22 // Spec pseudocode definition: 23 // def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSlashing) -> None: 24 // header_1 = proposer_slashing.signed_header_1.message 25 // header_2 = proposer_slashing.signed_header_2.message 26 // 27 // # Verify header slots match 28 // assert header_1.slot == header_2.slot 29 // # Verify header proposer indices match 30 // assert header_1.proposer_index == header_2.proposer_index 31 // # Verify the headers are different 32 // assert header_1 != header_2 33 // # Verify the proposer is slashable 34 // proposer = state.validators[header_1.proposer_index] 35 // assert is_slashable_validator(proposer, get_current_epoch(state)) 36 // # Verify signatures 37 // for signed_header in (proposer_slashing.signed_header_1, proposer_slashing.signed_header_2): 38 // domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(signed_header.message.slot)) 39 // signing_root = compute_signing_root(signed_header.message, domain) 40 // assert bls.Verify(proposer.pubkey, signing_root, signed_header.signature) 41 // 42 // slash_validator(state, header_1.proposer_index) 43 func ProcessProposerSlashings( 44 _ context.Context, 45 beaconState iface.BeaconState, 46 slashings []*ethpb.ProposerSlashing, 47 slashFunc slashValidatorFunc, 48 ) (iface.BeaconState, error) { 49 var err error 50 for idx, slashing := range slashings { 51 if slashing == nil { 52 return nil, errors.New("nil proposer slashings in block body") 53 } 54 if err = VerifyProposerSlashing(beaconState, slashing); err != nil { 55 return nil, errors.Wrapf(err, "could not verify proposer slashing %d", idx) 56 } 57 beaconState, err = slashFunc(beaconState, slashing.Header_1.Header.ProposerIndex) 58 if err != nil { 59 return nil, errors.Wrapf(err, "could not slash proposer index %d", slashing.Header_1.Header.ProposerIndex) 60 } 61 } 62 return beaconState, nil 63 } 64 65 // VerifyProposerSlashing verifies that the data provided from slashing is valid. 66 func VerifyProposerSlashing( 67 beaconState iface.BeaconState, 68 slashing *ethpb.ProposerSlashing, 69 ) error { 70 if slashing.Header_1 == nil || slashing.Header_1.Header == nil || slashing.Header_2 == nil || slashing.Header_2.Header == nil { 71 return errors.New("nil header cannot be verified") 72 } 73 hSlot := slashing.Header_1.Header.Slot 74 if hSlot != slashing.Header_2.Header.Slot { 75 return fmt.Errorf("mismatched header slots, received %d == %d", slashing.Header_1.Header.Slot, slashing.Header_2.Header.Slot) 76 } 77 pIdx := slashing.Header_1.Header.ProposerIndex 78 if pIdx != slashing.Header_2.Header.ProposerIndex { 79 return fmt.Errorf("mismatched indices, received %d == %d", slashing.Header_1.Header.ProposerIndex, slashing.Header_2.Header.ProposerIndex) 80 } 81 if proto.Equal(slashing.Header_1.Header, slashing.Header_2.Header) { 82 return errors.New("expected slashing headers to differ") 83 } 84 proposer, err := beaconState.ValidatorAtIndexReadOnly(slashing.Header_1.Header.ProposerIndex) 85 if err != nil { 86 return err 87 } 88 if !helpers.IsSlashableValidatorUsingTrie(proposer, helpers.CurrentEpoch(beaconState)) { 89 return fmt.Errorf("validator with key %#x is not slashable", proposer.PublicKey()) 90 } 91 headers := []*ethpb.SignedBeaconBlockHeader{slashing.Header_1, slashing.Header_2} 92 for _, header := range headers { 93 if err := helpers.ComputeDomainVerifySigningRoot(beaconState, pIdx, helpers.SlotToEpoch(hSlot), 94 header.Header, params.BeaconConfig().DomainBeaconProposer, header.Signature); err != nil { 95 return errors.Wrap(err, "could not verify beacon block header") 96 } 97 } 98 return nil 99 }