github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/blocks/header.go (about) 1 package blocks 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 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/proto/interfaces" 13 "github.com/prysmaticlabs/prysm/shared/params" 14 ) 15 16 // ProcessBlockHeader validates a block by its header. 17 // 18 // Spec pseudocode definition: 19 // 20 // def process_block_header(state: BeaconState, block: BeaconBlock) -> None: 21 // # Verify that the slots match 22 // assert block.slot == state.slot 23 // # Verify that the block is newer than latest block header 24 // assert block.slot > state.latest_block_header.slot 25 // # Verify that proposer index is the correct index 26 // assert block.proposer_index == get_beacon_proposer_index(state) 27 // # Verify that the parent matches 28 // assert block.parent_root == hash_tree_root(state.latest_block_header) 29 // # Cache current block as the new latest block 30 // state.latest_block_header = BeaconBlockHeader( 31 // slot=block.slot, 32 // proposer_index=block.proposer_index, 33 // parent_root=block.parent_root, 34 // state_root=Bytes32(), # Overwritten in the next process_slot call 35 // body_root=hash_tree_root(block.body), 36 // ) 37 // 38 // # Verify proposer is not slashed 39 // proposer = state.validators[block.proposer_index] 40 // assert not proposer.slashed 41 func ProcessBlockHeader( 42 _ context.Context, 43 beaconState iface.BeaconState, 44 block interfaces.SignedBeaconBlock, 45 ) (iface.BeaconState, error) { 46 if err := helpers.VerifyNilBeaconBlock(block); err != nil { 47 return nil, err 48 } 49 bodyRoot, err := block.Block().Body().HashTreeRoot() 50 if err != nil { 51 return nil, err 52 } 53 beaconState, err = ProcessBlockHeaderNoVerify(beaconState, block.Block().Slot(), block.Block().ProposerIndex(), block.Block().ParentRoot(), bodyRoot[:]) 54 if err != nil { 55 return nil, err 56 } 57 58 // Verify proposer signature. 59 if err := VerifyBlockSignature(beaconState, block.Block().ProposerIndex(), block.Signature(), block.Block().HashTreeRoot); err != nil { 60 return nil, err 61 } 62 63 return beaconState, nil 64 } 65 66 // ProcessBlockHeaderNoVerify validates a block by its header but skips proposer 67 // signature verification. 68 // 69 // WARNING: This method does not verify proposer signature. This is used for proposer to compute state root 70 // using a unsigned block. 71 // 72 // Spec pseudocode definition: 73 // def process_block_header(state: BeaconState, block: BeaconBlock) -> None: 74 // # Verify that the slots match 75 // assert block.slot == state.slot 76 // # Verify that the block is newer than latest block header 77 // assert block.slot > state.latest_block_header.slot 78 // # Verify that proposer index is the correct index 79 // assert block.proposer_index == get_beacon_proposer_index(state) 80 // # Verify that the parent matches 81 // assert block.parent_root == hash_tree_root(state.latest_block_header) 82 // # Cache current block as the new latest block 83 // state.latest_block_header = BeaconBlockHeader( 84 // slot=block.slot, 85 // proposer_index=block.proposer_index, 86 // parent_root=block.parent_root, 87 // state_root=Bytes32(), # Overwritten in the next process_slot call 88 // body_root=hash_tree_root(block.body), 89 // ) 90 // 91 // # Verify proposer is not slashed 92 // proposer = state.validators[block.proposer_index] 93 // assert not proposer.slashed 94 func ProcessBlockHeaderNoVerify( 95 beaconState iface.BeaconState, 96 slot types.Slot, proposerIndex types.ValidatorIndex, 97 parentRoot, bodyRoot []byte, 98 ) (iface.BeaconState, error) { 99 if beaconState.Slot() != slot { 100 return nil, fmt.Errorf("state slot: %d is different than block slot: %d", beaconState.Slot(), slot) 101 } 102 idx, err := helpers.BeaconProposerIndex(beaconState) 103 if err != nil { 104 return nil, err 105 } 106 if proposerIndex != idx { 107 return nil, fmt.Errorf("proposer index: %d is different than calculated: %d", proposerIndex, idx) 108 } 109 parentHeader := beaconState.LatestBlockHeader() 110 if parentHeader.Slot >= slot { 111 return nil, fmt.Errorf("block.Slot %d must be greater than state.LatestBlockHeader.Slot %d", slot, parentHeader.Slot) 112 } 113 parentHeaderRoot, err := parentHeader.HashTreeRoot() 114 if err != nil { 115 return nil, err 116 } 117 118 if !bytes.Equal(parentRoot, parentHeaderRoot[:]) { 119 return nil, fmt.Errorf( 120 "parent root %#x does not match the latest block header signing root in state %#x", 121 parentRoot, parentHeaderRoot[:]) 122 } 123 124 proposer, err := beaconState.ValidatorAtIndexReadOnly(idx) 125 if err != nil { 126 return nil, err 127 } 128 if proposer.Slashed() { 129 return nil, fmt.Errorf("proposer at index %d was previously slashed", idx) 130 } 131 132 if err := beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ 133 Slot: slot, 134 ProposerIndex: proposerIndex, 135 ParentRoot: parentRoot, 136 StateRoot: params.BeaconConfig().ZeroHash[:], 137 BodyRoot: bodyRoot, 138 }); err != nil { 139 return nil, err 140 } 141 return beaconState, nil 142 }