github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/blocks/header_test.go (about)

     1  package blocks_test
     2  
     3  import (
     4  	"context"
     5  	"io/ioutil"
     6  	"testing"
     7  
     8  	"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
     9  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    10  	p2ptypes "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types"
    11  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    12  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    13  	"github.com/prysmaticlabs/prysm/shared/bls"
    14  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    15  	"github.com/prysmaticlabs/prysm/shared/params"
    16  	"github.com/prysmaticlabs/prysm/shared/testutil"
    17  	"github.com/prysmaticlabs/prysm/shared/testutil/assert"
    18  	"github.com/prysmaticlabs/prysm/shared/testutil/require"
    19  	"github.com/sirupsen/logrus"
    20  	"google.golang.org/protobuf/proto"
    21  )
    22  
    23  func init() {
    24  	logrus.SetOutput(ioutil.Discard) // Ignore "validator activated" logs
    25  }
    26  
    27  func TestProcessBlockHeader_ImproperBlockSlot(t *testing.T) {
    28  	validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
    29  	for i := 0; i < len(validators); i++ {
    30  		validators[i] = &ethpb.Validator{
    31  			PublicKey:             make([]byte, 32),
    32  			WithdrawalCredentials: make([]byte, 32),
    33  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
    34  			Slashed:               true,
    35  		}
    36  	}
    37  
    38  	state, err := testutil.NewBeaconState()
    39  	require.NoError(t, err)
    40  	require.NoError(t, state.SetSlot(10))
    41  	require.NoError(t, state.SetValidators(validators))
    42  	require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
    43  		Slot: 10, // Must be less than block.Slot
    44  	})))
    45  
    46  	latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot()
    47  	require.NoError(t, err)
    48  
    49  	currentEpoch := helpers.CurrentEpoch(state)
    50  	priv, err := bls.RandKey()
    51  	require.NoError(t, err)
    52  	pID, err := helpers.BeaconProposerIndex(state)
    53  	require.NoError(t, err)
    54  	block := testutil.NewBeaconBlock()
    55  	block.Block.ProposerIndex = pID
    56  	block.Block.Slot = 10
    57  	block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
    58  	block.Block.ParentRoot = latestBlockSignedRoot[:]
    59  	block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv)
    60  	require.NoError(t, err)
    61  
    62  	proposerIdx, err := helpers.BeaconProposerIndex(state)
    63  	require.NoError(t, err)
    64  	validators[proposerIdx].Slashed = false
    65  	validators[proposerIdx].PublicKey = priv.PublicKey().Marshal()
    66  	err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
    67  	require.NoError(t, err)
    68  
    69  	_, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block))
    70  	assert.ErrorContains(t, "block.Slot 10 must be greater than state.LatestBlockHeader.Slot 10", err)
    71  }
    72  
    73  func TestProcessBlockHeader_WrongProposerSig(t *testing.T) {
    74  
    75  	beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
    76  	require.NoError(t, beaconState.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
    77  		Slot: 9,
    78  	})))
    79  	require.NoError(t, beaconState.SetSlot(10))
    80  
    81  	lbhdr, err := beaconState.LatestBlockHeader().HashTreeRoot()
    82  	require.NoError(t, err)
    83  
    84  	proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
    85  	require.NoError(t, err)
    86  
    87  	block := testutil.NewBeaconBlock()
    88  	block.Block.ProposerIndex = proposerIdx
    89  	block.Block.Slot = 10
    90  	block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
    91  	block.Block.ParentRoot = lbhdr[:]
    92  	block.Signature, err = helpers.ComputeDomainAndSign(beaconState, 0, block.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx+1])
    93  	require.NoError(t, err)
    94  
    95  	_, err = blocks.ProcessBlockHeader(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block))
    96  	want := "signature did not verify"
    97  	assert.ErrorContains(t, want, err)
    98  }
    99  
   100  func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
   101  	validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
   102  	for i := 0; i < len(validators); i++ {
   103  		validators[i] = &ethpb.Validator{
   104  			PublicKey:             make([]byte, 32),
   105  			WithdrawalCredentials: make([]byte, 32),
   106  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   107  			Slashed:               true,
   108  		}
   109  	}
   110  
   111  	state, err := testutil.NewBeaconState()
   112  	require.NoError(t, err)
   113  	require.NoError(t, state.SetValidators(validators))
   114  	require.NoError(t, state.SetSlot(10))
   115  	require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
   116  		Slot: 9,
   117  	})))
   118  
   119  	lbhsr, err := state.LatestBlockHeader().HashTreeRoot()
   120  	require.NoError(t, err)
   121  	currentEpoch := helpers.CurrentEpoch(state)
   122  
   123  	priv, err := bls.RandKey()
   124  	require.NoError(t, err)
   125  	sszBytes := p2ptypes.SSZBytes("hello")
   126  	blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
   127  	require.NoError(t, err)
   128  	validators[5896].PublicKey = priv.PublicKey().Marshal()
   129  	block := testutil.HydrateSignedBeaconBlock(&ethpb.SignedBeaconBlock{
   130  		Block: &ethpb.BeaconBlock{
   131  			Slot:       1,
   132  			ParentRoot: lbhsr[:],
   133  		},
   134  		Signature: blockSig,
   135  	})
   136  
   137  	_, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block))
   138  	want := "is different than block slot"
   139  	assert.ErrorContains(t, want, err)
   140  }
   141  
   142  func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
   143  	validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
   144  	for i := 0; i < len(validators); i++ {
   145  		validators[i] = &ethpb.Validator{
   146  			PublicKey:             make([]byte, 48),
   147  			WithdrawalCredentials: make([]byte, 32),
   148  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   149  			Slashed:               true,
   150  		}
   151  	}
   152  
   153  	state, err := testutil.NewBeaconState()
   154  	require.NoError(t, err)
   155  	require.NoError(t, state.SetValidators(validators))
   156  	require.NoError(t, state.SetSlot(10))
   157  	bh := state.LatestBlockHeader()
   158  	bh.Slot = 9
   159  	require.NoError(t, state.SetLatestBlockHeader(bh))
   160  	currentEpoch := helpers.CurrentEpoch(state)
   161  	priv, err := bls.RandKey()
   162  	require.NoError(t, err)
   163  	sszBytes := p2ptypes.SSZBytes("hello")
   164  	blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
   165  	require.NoError(t, err)
   166  	validators[5896].PublicKey = priv.PublicKey().Marshal()
   167  	pID, err := helpers.BeaconProposerIndex(state)
   168  	require.NoError(t, err)
   169  	block := testutil.NewBeaconBlock()
   170  	block.Block.Slot = 10
   171  	block.Block.ProposerIndex = pID
   172  	block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
   173  	block.Block.ParentRoot = bytesutil.PadTo([]byte{'A'}, 32)
   174  	block.Signature = blockSig
   175  
   176  	_, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block))
   177  	want := "does not match"
   178  	assert.ErrorContains(t, want, err)
   179  }
   180  
   181  func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
   182  	validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
   183  	for i := 0; i < len(validators); i++ {
   184  		validators[i] = &ethpb.Validator{
   185  			PublicKey:             make([]byte, 48),
   186  			WithdrawalCredentials: make([]byte, 32),
   187  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   188  			Slashed:               true,
   189  		}
   190  	}
   191  
   192  	state, err := testutil.NewBeaconState()
   193  	require.NoError(t, err)
   194  	require.NoError(t, state.SetValidators(validators))
   195  	require.NoError(t, state.SetSlot(10))
   196  	bh := state.LatestBlockHeader()
   197  	bh.Slot = 9
   198  	require.NoError(t, state.SetLatestBlockHeader(bh))
   199  	parentRoot, err := state.LatestBlockHeader().HashTreeRoot()
   200  	require.NoError(t, err)
   201  	currentEpoch := helpers.CurrentEpoch(state)
   202  	priv, err := bls.RandKey()
   203  	require.NoError(t, err)
   204  	sszBytes := p2ptypes.SSZBytes("hello")
   205  	blockSig, err := helpers.ComputeDomainAndSign(state, currentEpoch, &sszBytes, params.BeaconConfig().DomainBeaconProposer, priv)
   206  	require.NoError(t, err)
   207  
   208  	validators[12683].PublicKey = priv.PublicKey().Marshal()
   209  	pID, err := helpers.BeaconProposerIndex(state)
   210  	require.NoError(t, err)
   211  	block := testutil.NewBeaconBlock()
   212  	block.Block.Slot = 10
   213  	block.Block.ProposerIndex = pID
   214  	block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
   215  	block.Block.ParentRoot = parentRoot[:]
   216  	block.Signature = blockSig
   217  
   218  	_, err = blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block))
   219  	want := "was previously slashed"
   220  	assert.ErrorContains(t, want, err)
   221  }
   222  
   223  func TestProcessBlockHeader_OK(t *testing.T) {
   224  	validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
   225  	for i := 0; i < len(validators); i++ {
   226  		validators[i] = &ethpb.Validator{
   227  			PublicKey:             make([]byte, 32),
   228  			WithdrawalCredentials: make([]byte, 32),
   229  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   230  			Slashed:               true,
   231  		}
   232  	}
   233  
   234  	state, err := testutil.NewBeaconState()
   235  	require.NoError(t, err)
   236  	require.NoError(t, state.SetValidators(validators))
   237  	require.NoError(t, state.SetSlot(10))
   238  	require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
   239  		Slot: 9,
   240  	})))
   241  
   242  	latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot()
   243  	require.NoError(t, err)
   244  
   245  	currentEpoch := helpers.CurrentEpoch(state)
   246  	priv, err := bls.RandKey()
   247  	require.NoError(t, err)
   248  	pID, err := helpers.BeaconProposerIndex(state)
   249  	require.NoError(t, err)
   250  	block := testutil.NewBeaconBlock()
   251  	block.Block.ProposerIndex = pID
   252  	block.Block.Slot = 10
   253  	block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
   254  	block.Block.ParentRoot = latestBlockSignedRoot[:]
   255  	block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv)
   256  	require.NoError(t, err)
   257  	bodyRoot, err := block.Block.Body.HashTreeRoot()
   258  	require.NoError(t, err, "Failed to hash block bytes got")
   259  
   260  	proposerIdx, err := helpers.BeaconProposerIndex(state)
   261  	require.NoError(t, err)
   262  	validators[proposerIdx].Slashed = false
   263  	validators[proposerIdx].PublicKey = priv.PublicKey().Marshal()
   264  	err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
   265  	require.NoError(t, err)
   266  
   267  	newState, err := blocks.ProcessBlockHeader(context.Background(), state, wrapper.WrappedPhase0SignedBeaconBlock(block))
   268  	require.NoError(t, err, "Failed to process block header got")
   269  	var zeroHash [32]byte
   270  	nsh := newState.LatestBlockHeader()
   271  	expected := &ethpb.BeaconBlockHeader{
   272  		ProposerIndex: pID,
   273  		Slot:          block.Block.Slot,
   274  		ParentRoot:    latestBlockSignedRoot[:],
   275  		BodyRoot:      bodyRoot[:],
   276  		StateRoot:     zeroHash[:],
   277  	}
   278  	assert.Equal(t, true, proto.Equal(nsh, expected), "Expected %v, received %v", expected, nsh)
   279  }
   280  
   281  func TestBlockSignatureSet_OK(t *testing.T) {
   282  	validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
   283  	for i := 0; i < len(validators); i++ {
   284  		validators[i] = &ethpb.Validator{
   285  			PublicKey:             make([]byte, 32),
   286  			WithdrawalCredentials: make([]byte, 32),
   287  			ExitEpoch:             params.BeaconConfig().FarFutureEpoch,
   288  			Slashed:               true,
   289  		}
   290  	}
   291  
   292  	state, err := testutil.NewBeaconState()
   293  	require.NoError(t, err)
   294  	require.NoError(t, state.SetValidators(validators))
   295  	require.NoError(t, state.SetSlot(10))
   296  	require.NoError(t, state.SetLatestBlockHeader(testutil.HydrateBeaconHeader(&ethpb.BeaconBlockHeader{
   297  		Slot:          9,
   298  		ProposerIndex: 0,
   299  	})))
   300  
   301  	latestBlockSignedRoot, err := state.LatestBlockHeader().HashTreeRoot()
   302  	require.NoError(t, err)
   303  
   304  	currentEpoch := helpers.CurrentEpoch(state)
   305  	priv, err := bls.RandKey()
   306  	require.NoError(t, err)
   307  	pID, err := helpers.BeaconProposerIndex(state)
   308  	require.NoError(t, err)
   309  	block := testutil.NewBeaconBlock()
   310  	block.Block.Slot = 10
   311  	block.Block.ProposerIndex = pID
   312  	block.Block.Body.RandaoReveal = bytesutil.PadTo([]byte{'A', 'B', 'C'}, 96)
   313  	block.Block.ParentRoot = latestBlockSignedRoot[:]
   314  	block.Signature, err = helpers.ComputeDomainAndSign(state, currentEpoch, block.Block, params.BeaconConfig().DomainBeaconProposer, priv)
   315  	require.NoError(t, err)
   316  	proposerIdx, err := helpers.BeaconProposerIndex(state)
   317  	require.NoError(t, err)
   318  	validators[proposerIdx].Slashed = false
   319  	validators[proposerIdx].PublicKey = priv.PublicKey().Marshal()
   320  	err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
   321  	require.NoError(t, err)
   322  	set, err := blocks.BlockSignatureSet(state, block.Block.ProposerIndex, block.Signature, block.Block.HashTreeRoot)
   323  	require.NoError(t, err)
   324  
   325  	verified, err := set.Verify()
   326  	require.NoError(t, err)
   327  	assert.Equal(t, true, verified, "Block signature set returned a set which was unable to be verified")
   328  }