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 = ðpb.BeaconBlock{ 31 Body: ðpb.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 := ðpb.Deposit{ 61 Data: ðpb.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 = ðpb.BeaconBlock{ 79 Body: ðpb.BeaconBlockBody{ 80 Deposits: []*ethpb.Deposit{deposit}, 81 }, 82 } 83 beaconState, err := v1.InitializeFromProto(&pb.BeaconState{ 84 Eth1Data: ðpb.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 = ðpb.BeaconBlock{ 103 Body: ðpb.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 := ðpb.Deposit{ 139 Data: ðpb.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 = ðpb.BeaconBlock{ 162 Body: ðpb.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: ðpb.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 := ðpb.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 := ðpb.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 }