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

     1  package blocks_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	types "github.com/prysmaticlabs/eth2-types"
     8  	"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
     9  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
    10  	"github.com/prysmaticlabs/prysm/beacon-chain/state/v1"
    11  	pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
    12  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    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/prysmaticlabs/prysm/shared/trieutil"
    20  )
    21  
    22  func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
    23  	// Same validator created 3 valid deposits within the same block
    24  
    25  	dep, _, err := testutil.DeterministicDepositsAndKeysSameValidator(3)
    26  	require.NoError(t, err)
    27  	eth1Data, err := testutil.DeterministicEth1Data(len(dep))
    28  	require.NoError(t, err)
    29  	b := testutil.NewBeaconBlock()
    30  	b.Block = &ethpb.BeaconBlock{
    31  		Body: &ethpb.BeaconBlockBody{
    32  			// 3 deposits from the same validator
    33  			Deposits: []*ethpb.Deposit{dep[0], dep[1], dep[2]},
    34  		},
    35  	}
    36  	registry := []*ethpb.Validator{
    37  		{
    38  			PublicKey:             []byte{1},
    39  			WithdrawalCredentials: []byte{1, 2, 3},
    40  		},
    41  	}
    42  	balances := []uint64{0}
    43  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
    44  		Validators: registry,
    45  		Balances:   balances,
    46  		Eth1Data:   eth1Data,
    47  		Fork: &pb.Fork{
    48  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
    49  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
    50  		},
    51  	})
    52  	require.NoError(t, err)
    53  	newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
    54  	require.NoError(t, err, "Expected block deposits to process correctly")
    55  
    56  	assert.Equal(t, 2, len(newState.Validators()), "Incorrect validator count")
    57  }
    58  
    59  func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
    60  	deposit := &ethpb.Deposit{
    61  		Data: &ethpb.Deposit_Data{
    62  			PublicKey:             bytesutil.PadTo([]byte{1, 2, 3}, 48),
    63  			WithdrawalCredentials: make([]byte, 32),
    64  			Signature:             make([]byte, 96),
    65  		},
    66  	}
    67  	leaf, err := deposit.Data.HashTreeRoot()
    68  	require.NoError(t, err)
    69  
    70  	// We then create a merkle branch for the test.
    71  	depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
    72  	require.NoError(t, err, "Could not generate trie")
    73  	proof, err := depositTrie.MerkleProof(0)
    74  	require.NoError(t, err, "Could not generate proof")
    75  
    76  	deposit.Proof = proof
    77  	b := testutil.NewBeaconBlock()
    78  	b.Block = &ethpb.BeaconBlock{
    79  		Body: &ethpb.BeaconBlockBody{
    80  			Deposits: []*ethpb.Deposit{deposit},
    81  		},
    82  	}
    83  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
    84  		Eth1Data: &ethpb.Eth1Data{
    85  			DepositRoot: []byte{0},
    86  			BlockHash:   []byte{1},
    87  		},
    88  	})
    89  	require.NoError(t, err)
    90  	want := "deposit root did not verify"
    91  	_, err = blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
    92  	assert.ErrorContains(t, want, err)
    93  }
    94  
    95  func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
    96  	dep, _, err := testutil.DeterministicDepositsAndKeys(1)
    97  	require.NoError(t, err)
    98  	eth1Data, err := testutil.DeterministicEth1Data(len(dep))
    99  	require.NoError(t, err)
   100  
   101  	b := testutil.NewBeaconBlock()
   102  	b.Block = &ethpb.BeaconBlock{
   103  		Body: &ethpb.BeaconBlockBody{
   104  			Deposits: []*ethpb.Deposit{dep[0]},
   105  		},
   106  	}
   107  	registry := []*ethpb.Validator{
   108  		{
   109  			PublicKey:             []byte{1},
   110  			WithdrawalCredentials: []byte{1, 2, 3},
   111  		},
   112  	}
   113  	balances := []uint64{0}
   114  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
   115  		Validators: registry,
   116  		Balances:   balances,
   117  		Eth1Data:   eth1Data,
   118  		Fork: &pb.Fork{
   119  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
   120  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
   121  		},
   122  	})
   123  	require.NoError(t, err)
   124  	newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
   125  	require.NoError(t, err, "Expected block deposits to process correctly")
   126  	if newState.Balances()[1] != dep[0].Data.Amount {
   127  		t.Errorf(
   128  			"Expected state validator balances index 0 to equal %d, received %d",
   129  			dep[0].Data.Amount,
   130  			newState.Balances()[1],
   131  		)
   132  	}
   133  }
   134  
   135  func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T) {
   136  	sk, err := bls.RandKey()
   137  	require.NoError(t, err)
   138  	deposit := &ethpb.Deposit{
   139  		Data: &ethpb.Deposit_Data{
   140  			PublicKey:             sk.PublicKey().Marshal(),
   141  			Amount:                1000,
   142  			WithdrawalCredentials: make([]byte, 32),
   143  			Signature:             make([]byte, 96),
   144  		},
   145  	}
   146  	sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 32))
   147  	require.NoError(t, err)
   148  	sig := sk.Sign(sr[:])
   149  	deposit.Data.Signature = sig.Marshal()
   150  	leaf, err := deposit.Data.HashTreeRoot()
   151  	require.NoError(t, err)
   152  
   153  	// We then create a merkle branch for the test.
   154  	depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
   155  	require.NoError(t, err, "Could not generate trie")
   156  	proof, err := depositTrie.MerkleProof(0)
   157  	require.NoError(t, err, "Could not generate proof")
   158  
   159  	deposit.Proof = proof
   160  	b := testutil.NewBeaconBlock()
   161  	b.Block = &ethpb.BeaconBlock{
   162  		Body: &ethpb.BeaconBlockBody{
   163  			Deposits: []*ethpb.Deposit{deposit},
   164  		},
   165  	}
   166  	registry := []*ethpb.Validator{
   167  		{
   168  			PublicKey: []byte{1, 2, 3},
   169  		},
   170  		{
   171  			PublicKey:             sk.PublicKey().Marshal(),
   172  			WithdrawalCredentials: []byte{1},
   173  		},
   174  	}
   175  	balances := []uint64{0, 50}
   176  	root := depositTrie.Root()
   177  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
   178  		Validators: registry,
   179  		Balances:   balances,
   180  		Eth1Data: &ethpb.Eth1Data{
   181  			DepositRoot: root[:],
   182  			BlockHash:   root[:],
   183  		},
   184  	})
   185  	require.NoError(t, err)
   186  	newState, err := blocks.ProcessDeposits(context.Background(), beaconState, b.Block.Body.Deposits)
   187  	require.NoError(t, err, "Process deposit failed")
   188  	assert.Equal(t, uint64(1000+50), newState.Balances()[1], "Expected balance at index 1 to be 1050")
   189  }
   190  
   191  func TestProcessDeposit_AddsNewValidatorDeposit(t *testing.T) {
   192  	// Similar to TestProcessDeposits_AddsNewValidatorDeposit except that this test directly calls ProcessDeposit
   193  	dep, _, err := testutil.DeterministicDepositsAndKeys(1)
   194  	require.NoError(t, err)
   195  	eth1Data, err := testutil.DeterministicEth1Data(len(dep))
   196  	require.NoError(t, err)
   197  
   198  	registry := []*ethpb.Validator{
   199  		{
   200  			PublicKey:             []byte{1},
   201  			WithdrawalCredentials: []byte{1, 2, 3},
   202  		},
   203  	}
   204  	balances := []uint64{0}
   205  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
   206  		Validators: registry,
   207  		Balances:   balances,
   208  		Eth1Data:   eth1Data,
   209  		Fork: &pb.Fork{
   210  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
   211  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
   212  		},
   213  	})
   214  	require.NoError(t, err)
   215  	newState, err := blocks.ProcessDeposit(beaconState, dep[0], true)
   216  	require.NoError(t, err, "Process deposit failed")
   217  	assert.Equal(t, 2, len(newState.Validators()), "Expected validator list to have length 2")
   218  	assert.Equal(t, 2, len(newState.Balances()), "Expected validator balances list to have length 2")
   219  	if newState.Balances()[1] != dep[0].Data.Amount {
   220  		t.Errorf(
   221  			"Expected state validator balances index 1 to equal %d, received %d",
   222  			dep[0].Data.Amount,
   223  			newState.Balances()[1],
   224  		)
   225  	}
   226  }
   227  
   228  func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
   229  	// Same test settings as in TestProcessDeposit_AddsNewValidatorDeposit, except that we use an invalid signature
   230  	dep, _, err := testutil.DeterministicDepositsAndKeys(1)
   231  	require.NoError(t, err)
   232  	dep[0].Data.Signature = make([]byte, 96)
   233  	trie, _, err := testutil.DepositTrieFromDeposits(dep)
   234  	require.NoError(t, err)
   235  	root := trie.Root()
   236  	eth1Data := &ethpb.Eth1Data{
   237  		DepositRoot:  root[:],
   238  		DepositCount: 1,
   239  	}
   240  	registry := []*ethpb.Validator{
   241  		{
   242  			PublicKey:             []byte{1},
   243  			WithdrawalCredentials: []byte{1, 2, 3},
   244  		},
   245  	}
   246  	balances := []uint64{0}
   247  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
   248  		Validators: registry,
   249  		Balances:   balances,
   250  		Eth1Data:   eth1Data,
   251  		Fork: &pb.Fork{
   252  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
   253  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
   254  		},
   255  	})
   256  	require.NoError(t, err)
   257  	newState, err := blocks.ProcessDeposit(beaconState, dep[0], true)
   258  	require.NoError(t, err, "Expected invalid block deposit to be ignored without error")
   259  
   260  	if newState.Eth1DepositIndex() != 1 {
   261  		t.Errorf(
   262  			"Expected Eth1DepositIndex to be increased by 1 after processing an invalid deposit, received change: %v",
   263  			newState.Eth1DepositIndex(),
   264  		)
   265  	}
   266  	if len(newState.Validators()) != 1 {
   267  		t.Errorf("Expected validator list to have length 1, received: %v", len(newState.Validators()))
   268  	}
   269  	if len(newState.Balances()) != 1 {
   270  		t.Errorf("Expected validator balances list to have length 1, received: %v", len(newState.Balances()))
   271  	}
   272  	if newState.Balances()[0] != 0 {
   273  		t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
   274  	}
   275  }
   276  
   277  func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
   278  
   279  	dep, _, err := testutil.DeterministicDepositsAndKeys(100)
   280  	require.NoError(t, err)
   281  	dep[0].Data.Signature = make([]byte, 96)
   282  	trie, _, err := testutil.DepositTrieFromDeposits(dep)
   283  	require.NoError(t, err)
   284  
   285  	for i := range dep {
   286  		proof, err := trie.MerkleProof(i)
   287  		require.NoError(t, err)
   288  		dep[i].Proof = proof
   289  	}
   290  	root := trie.Root()
   291  	eth1Data := &ethpb.Eth1Data{
   292  		DepositRoot:  root[:],
   293  		DepositCount: 1,
   294  	}
   295  	registry := []*ethpb.Validator{
   296  		{
   297  			PublicKey:             []byte{1},
   298  			WithdrawalCredentials: []byte{1, 2, 3},
   299  		},
   300  	}
   301  	balances := []uint64{0}
   302  	beaconState, err := v1.InitializeFromProto(&pb.BeaconState{
   303  		Validators: registry,
   304  		Balances:   balances,
   305  		Eth1Data:   eth1Data,
   306  		Fork: &pb.Fork{
   307  			PreviousVersion: params.BeaconConfig().GenesisForkVersion,
   308  			CurrentVersion:  params.BeaconConfig().GenesisForkVersion,
   309  		},
   310  	})
   311  	require.NoError(t, err)
   312  	newState, err := blocks.ProcessPreGenesisDeposits(context.Background(), beaconState, dep)
   313  	require.NoError(t, err, "Expected invalid block deposit to be ignored without error")
   314  
   315  	_, ok := newState.ValidatorIndexByPubkey(bytesutil.ToBytes48(dep[0].Data.PublicKey))
   316  	require.Equal(t, false, ok, "bad pubkey should not exist in state")
   317  
   318  	for i := 1; i < newState.NumValidators(); i++ {
   319  		val, err := newState.ValidatorAtIndex(types.ValidatorIndex(i))
   320  		require.NoError(t, err)
   321  		require.Equal(t, params.BeaconConfig().MaxEffectiveBalance, val.EffectiveBalance, "unequal effective balance")
   322  		require.Equal(t, types.Epoch(0), val.ActivationEpoch)
   323  		require.Equal(t, types.Epoch(0), val.ActivationEligibilityEpoch)
   324  	}
   325  	if newState.Eth1DepositIndex() != 100 {
   326  		t.Errorf(
   327  			"Expected Eth1DepositIndex to be increased by 99 after processing an invalid deposit, received change: %v",
   328  			newState.Eth1DepositIndex(),
   329  		)
   330  	}
   331  	if len(newState.Validators()) != 100 {
   332  		t.Errorf("Expected validator list to have length 100, received: %v", len(newState.Validators()))
   333  	}
   334  	if len(newState.Balances()) != 100 {
   335  		t.Errorf("Expected validator balances list to have length 100, received: %v", len(newState.Balances()))
   336  	}
   337  	if newState.Balances()[0] != 0 {
   338  		t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
   339  	}
   340  }