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(&ethpb.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  }