github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/state/transition_test.go (about) 1 package state_test 2 3 import ( 4 "context" 5 "encoding/binary" 6 "fmt" 7 "testing" 8 9 types "github.com/prysmaticlabs/eth2-types" 10 "github.com/prysmaticlabs/go-bitfield" 11 "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks" 12 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 13 "github.com/prysmaticlabs/prysm/beacon-chain/core/state" 14 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 15 "github.com/prysmaticlabs/prysm/beacon-chain/state/v1" 16 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 17 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 18 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 19 "github.com/prysmaticlabs/prysm/shared/attestationutil" 20 "github.com/prysmaticlabs/prysm/shared/bls" 21 "github.com/prysmaticlabs/prysm/shared/bytesutil" 22 "github.com/prysmaticlabs/prysm/shared/hashutil" 23 "github.com/prysmaticlabs/prysm/shared/params" 24 "github.com/prysmaticlabs/prysm/shared/testutil" 25 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 26 "github.com/prysmaticlabs/prysm/shared/testutil/require" 27 "github.com/prysmaticlabs/prysm/shared/trieutil" 28 "github.com/sirupsen/logrus" 29 ) 30 31 func init() { 32 state.SkipSlotCache.Disable() 33 } 34 35 func TestExecuteStateTransition_IncorrectSlot(t *testing.T) { 36 base := &pb.BeaconState{ 37 Slot: 5, 38 } 39 beaconState, err := v1.InitializeFromProto(base) 40 require.NoError(t, err) 41 block := ðpb.SignedBeaconBlock{ 42 Block: ðpb.BeaconBlock{ 43 Slot: 4, 44 Body: ðpb.BeaconBlockBody{}, 45 }, 46 } 47 want := "expected state.slot" 48 _, err = state.ExecuteStateTransition(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 49 assert.ErrorContains(t, want, err) 50 } 51 52 func TestExecuteStateTransition_FullProcess(t *testing.T) { 53 beaconState, privKeys := testutil.DeterministicGenesisState(t, 100) 54 55 eth1Data := ðpb.Eth1Data{ 56 DepositCount: 100, 57 DepositRoot: bytesutil.PadTo([]byte{2}, 32), 58 BlockHash: make([]byte, 32), 59 } 60 require.NoError(t, beaconState.SetSlot(params.BeaconConfig().SlotsPerEpoch-1)) 61 e := beaconState.Eth1Data() 62 e.DepositCount = 100 63 require.NoError(t, beaconState.SetEth1Data(e)) 64 bh := beaconState.LatestBlockHeader() 65 bh.Slot = beaconState.Slot() 66 require.NoError(t, beaconState.SetLatestBlockHeader(bh)) 67 require.NoError(t, beaconState.SetEth1DataVotes([]*ethpb.Eth1Data{eth1Data})) 68 69 oldMix, err := beaconState.RandaoMixAtIndex(1) 70 require.NoError(t, err) 71 72 require.NoError(t, beaconState.SetSlot(beaconState.Slot()+1)) 73 epoch := helpers.CurrentEpoch(beaconState) 74 randaoReveal, err := testutil.RandaoReveal(beaconState, epoch, privKeys) 75 require.NoError(t, err) 76 require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1)) 77 78 nextSlotState, err := state.ProcessSlots(context.Background(), beaconState.Copy(), beaconState.Slot()+1) 79 require.NoError(t, err) 80 parentRoot, err := nextSlotState.LatestBlockHeader().HashTreeRoot() 81 require.NoError(t, err) 82 proposerIdx, err := helpers.BeaconProposerIndex(nextSlotState) 83 require.NoError(t, err) 84 block := testutil.NewBeaconBlock() 85 block.Block.ProposerIndex = proposerIdx 86 block.Block.Slot = beaconState.Slot() + 1 87 block.Block.ParentRoot = parentRoot[:] 88 block.Block.Body.RandaoReveal = randaoReveal 89 block.Block.Body.Eth1Data = eth1Data 90 91 stateRoot, err := state.CalculateStateRoot(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 92 require.NoError(t, err) 93 94 block.Block.StateRoot = stateRoot[:] 95 96 sig, err := testutil.BlockSignature(beaconState, block.Block, privKeys) 97 require.NoError(t, err) 98 block.Signature = sig.Marshal() 99 100 beaconState, err = state.ExecuteStateTransition(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 101 require.NoError(t, err) 102 103 assert.Equal(t, params.BeaconConfig().SlotsPerEpoch, beaconState.Slot(), "Unexpected Slot number") 104 105 mix, err := beaconState.RandaoMixAtIndex(1) 106 require.NoError(t, err) 107 assert.DeepNotEqual(t, oldMix, mix, "Did not expect new and old randao mix to equal") 108 } 109 110 func TestProcessBlock_IncorrectProposerSlashing(t *testing.T) { 111 beaconState, privKeys := testutil.DeterministicGenesisState(t, 100) 112 113 block, err := testutil.GenerateFullBlock(beaconState, privKeys, nil, 1) 114 require.NoError(t, err) 115 slashing := ðpb.ProposerSlashing{ 116 Header_1: testutil.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 117 Header: ðpb.BeaconBlockHeader{ 118 Slot: params.BeaconConfig().SlotsPerEpoch, 119 }, 120 }), 121 Header_2: testutil.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 122 Header: ðpb.BeaconBlockHeader{ 123 Slot: params.BeaconConfig().SlotsPerEpoch * 2, 124 }, 125 }), 126 } 127 block.Block.Body.ProposerSlashings = []*ethpb.ProposerSlashing{slashing} 128 129 require.NoError(t, beaconState.SetSlot(beaconState.Slot()+1)) 130 proposerIdx, err := helpers.BeaconProposerIndex(beaconState) 131 require.NoError(t, err) 132 require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1)) 133 block.Signature, err = helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), block.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) 134 require.NoError(t, err) 135 136 beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1) 137 require.NoError(t, err) 138 want := "could not verify proposer slashing" 139 _, err = state.ProcessBlock(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 140 assert.ErrorContains(t, want, err) 141 } 142 143 func TestProcessBlock_IncorrectProcessBlockAttestations(t *testing.T) { 144 beaconState, privKeys := testutil.DeterministicGenesisState(t, 100) 145 priv, err := bls.RandKey() 146 require.NoError(t, err) 147 att := testutil.HydrateAttestation(ðpb.Attestation{ 148 AggregationBits: bitfield.NewBitlist(3), 149 Signature: priv.Sign([]byte("foo")).Marshal(), 150 }) 151 152 block, err := testutil.GenerateFullBlock(beaconState, privKeys, nil, 1) 153 require.NoError(t, err) 154 block.Block.Body.Attestations = []*ethpb.Attestation{att} 155 require.NoError(t, beaconState.SetSlot(beaconState.Slot()+1)) 156 proposerIdx, err := helpers.BeaconProposerIndex(beaconState) 157 require.NoError(t, err) 158 require.NoError(t, beaconState.SetSlot(beaconState.Slot()-1)) 159 block.Signature, err = helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), block.Block, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerIdx]) 160 require.NoError(t, err) 161 162 beaconState, err = state.ProcessSlots(context.Background(), beaconState, 1) 163 require.NoError(t, err) 164 165 want := "could not verify attestation" 166 _, err = state.ProcessBlock(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 167 assert.ErrorContains(t, want, err) 168 } 169 170 func TestProcessBlock_IncorrectProcessExits(t *testing.T) { 171 beaconState, _ := testutil.DeterministicGenesisState(t, 100) 172 173 proposerSlashings := []*ethpb.ProposerSlashing{ 174 { 175 Header_1: testutil.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 176 Header: ðpb.BeaconBlockHeader{ 177 ProposerIndex: 3, 178 Slot: 1, 179 }, 180 Signature: bytesutil.PadTo([]byte("A"), 96), 181 }), 182 Header_2: testutil.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 183 Header: ðpb.BeaconBlockHeader{ 184 ProposerIndex: 3, 185 Slot: 1, 186 }, 187 Signature: bytesutil.PadTo([]byte("B"), 96), 188 }), 189 }, 190 } 191 attesterSlashings := []*ethpb.AttesterSlashing{ 192 { 193 Attestation_1: ðpb.IndexedAttestation{ 194 Data: testutil.HydrateAttestationData(ðpb.AttestationData{}), 195 AttestingIndices: []uint64{0, 1}, 196 Signature: make([]byte, 96), 197 }, 198 Attestation_2: ðpb.IndexedAttestation{ 199 Data: testutil.HydrateAttestationData(ðpb.AttestationData{}), 200 AttestingIndices: []uint64{0, 1}, 201 Signature: make([]byte, 96), 202 }, 203 }, 204 } 205 var blockRoots [][]byte 206 for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ { 207 blockRoots = append(blockRoots, []byte{byte(i)}) 208 } 209 require.NoError(t, beaconState.SetBlockRoots(blockRoots)) 210 blockAtt := testutil.HydrateAttestation(ðpb.Attestation{ 211 Data: ðpb.AttestationData{ 212 Target: ðpb.Checkpoint{Root: bytesutil.PadTo([]byte("hello-world"), 32)}, 213 }, 214 AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0x01}, 215 }) 216 attestations := []*ethpb.Attestation{blockAtt} 217 var exits []*ethpb.SignedVoluntaryExit 218 for i := uint64(0); i < params.BeaconConfig().MaxVoluntaryExits+1; i++ { 219 exits = append(exits, ðpb.SignedVoluntaryExit{}) 220 } 221 genesisBlock := blocks.NewGenesisBlock([]byte{}) 222 bodyRoot, err := genesisBlock.Block.HashTreeRoot() 223 require.NoError(t, err) 224 err = beaconState.SetLatestBlockHeader(testutil.HydrateBeaconHeader(ðpb.BeaconBlockHeader{ 225 Slot: genesisBlock.Block.Slot, 226 ParentRoot: genesisBlock.Block.ParentRoot, 227 BodyRoot: bodyRoot[:], 228 })) 229 require.NoError(t, err) 230 parentRoot, err := beaconState.LatestBlockHeader().HashTreeRoot() 231 require.NoError(t, err) 232 block := testutil.NewBeaconBlock() 233 block.Block.Slot = 1 234 block.Block.ParentRoot = parentRoot[:] 235 block.Block.Body.ProposerSlashings = proposerSlashings 236 block.Block.Body.Attestations = attestations 237 block.Block.Body.AttesterSlashings = attesterSlashings 238 block.Block.Body.VoluntaryExits = exits 239 block.Block.Body.Eth1Data.DepositRoot = bytesutil.PadTo([]byte{2}, 32) 240 block.Block.Body.Eth1Data.BlockHash = bytesutil.PadTo([]byte{3}, 32) 241 err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay) 242 require.NoError(t, err) 243 cp := beaconState.CurrentJustifiedCheckpoint() 244 cp.Root = []byte("hello-world") 245 require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp)) 246 require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{})) 247 _, err = state.VerifyOperationLengths(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 248 wanted := "number of voluntary exits (17) in block body exceeds allowed threshold of 16" 249 assert.ErrorContains(t, wanted, err) 250 } 251 252 func createFullBlockWithOperations(t *testing.T) (iface.BeaconState, 253 *ethpb.SignedBeaconBlock, []*ethpb.Attestation, []*ethpb.ProposerSlashing, []*ethpb.SignedVoluntaryExit) { 254 beaconState, privKeys := testutil.DeterministicGenesisState(t, 32) 255 genesisBlock := blocks.NewGenesisBlock([]byte{}) 256 bodyRoot, err := genesisBlock.Block.HashTreeRoot() 257 require.NoError(t, err) 258 err = beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{ 259 Slot: genesisBlock.Block.Slot, 260 ParentRoot: genesisBlock.Block.ParentRoot, 261 StateRoot: params.BeaconConfig().ZeroHash[:], 262 BodyRoot: bodyRoot[:], 263 }) 264 require.NoError(t, err) 265 err = beaconState.SetSlashings(make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector)) 266 require.NoError(t, err) 267 cp := beaconState.CurrentJustifiedCheckpoint() 268 mockRoot := [32]byte{} 269 copy(mockRoot[:], "hello-world") 270 cp.Root = mockRoot[:] 271 require.NoError(t, beaconState.SetCurrentJustifiedCheckpoint(cp)) 272 require.NoError(t, beaconState.AppendCurrentEpochAttestations(&pb.PendingAttestation{})) 273 274 proposerSlashIdx := types.ValidatorIndex(3) 275 slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch 276 err = beaconState.SetSlot(slotsPerEpoch.Mul(uint64(params.BeaconConfig().ShardCommitteePeriod)) + params.BeaconConfig().MinAttestationInclusionDelay) 277 require.NoError(t, err) 278 279 currentEpoch := helpers.CurrentEpoch(beaconState) 280 header1 := testutil.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 281 Header: ðpb.BeaconBlockHeader{ 282 ProposerIndex: proposerSlashIdx, 283 Slot: 1, 284 StateRoot: bytesutil.PadTo([]byte("A"), 32), 285 }, 286 }) 287 header1.Signature, err = helpers.ComputeDomainAndSign(beaconState, currentEpoch, header1.Header, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerSlashIdx]) 288 require.NoError(t, err) 289 290 header2 := testutil.HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 291 Header: ðpb.BeaconBlockHeader{ 292 ProposerIndex: proposerSlashIdx, 293 Slot: 1, 294 StateRoot: bytesutil.PadTo([]byte("B"), 32), 295 }, 296 }) 297 header2.Signature, err = helpers.ComputeDomainAndSign(beaconState, helpers.CurrentEpoch(beaconState), header2.Header, params.BeaconConfig().DomainBeaconProposer, privKeys[proposerSlashIdx]) 298 require.NoError(t, err) 299 300 proposerSlashings := []*ethpb.ProposerSlashing{ 301 { 302 Header_1: header1, 303 Header_2: header2, 304 }, 305 } 306 validators := beaconState.Validators() 307 validators[proposerSlashIdx].PublicKey = privKeys[proposerSlashIdx].PublicKey().Marshal() 308 require.NoError(t, beaconState.SetValidators(validators)) 309 310 mockRoot2 := [32]byte{'A'} 311 att1 := testutil.HydrateIndexedAttestation(ðpb.IndexedAttestation{ 312 Data: ðpb.AttestationData{ 313 Source: ðpb.Checkpoint{Epoch: 0, Root: mockRoot2[:]}, 314 }, 315 AttestingIndices: []uint64{0, 1}, 316 }) 317 domain, err := helpers.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot()) 318 require.NoError(t, err) 319 hashTreeRoot, err := helpers.ComputeSigningRoot(att1.Data, domain) 320 require.NoError(t, err) 321 sig0 := privKeys[0].Sign(hashTreeRoot[:]) 322 sig1 := privKeys[1].Sign(hashTreeRoot[:]) 323 aggregateSig := bls.AggregateSignatures([]bls.Signature{sig0, sig1}) 324 att1.Signature = aggregateSig.Marshal() 325 326 mockRoot3 := [32]byte{'B'} 327 att2 := testutil.HydrateIndexedAttestation(ðpb.IndexedAttestation{ 328 Data: ðpb.AttestationData{ 329 Source: ðpb.Checkpoint{Epoch: 0, Root: mockRoot3[:]}, 330 Target: ðpb.Checkpoint{Epoch: 0, Root: make([]byte, 32)}, 331 }, 332 AttestingIndices: []uint64{0, 1}, 333 }) 334 335 hashTreeRoot, err = helpers.ComputeSigningRoot(att2.Data, domain) 336 require.NoError(t, err) 337 sig0 = privKeys[0].Sign(hashTreeRoot[:]) 338 sig1 = privKeys[1].Sign(hashTreeRoot[:]) 339 aggregateSig = bls.AggregateSignatures([]bls.Signature{sig0, sig1}) 340 att2.Signature = aggregateSig.Marshal() 341 342 attesterSlashings := []*ethpb.AttesterSlashing{ 343 { 344 Attestation_1: att1, 345 Attestation_2: att2, 346 }, 347 } 348 349 var blockRoots [][]byte 350 for i := uint64(0); i < uint64(params.BeaconConfig().SlotsPerHistoricalRoot); i++ { 351 blockRoots = append(blockRoots, []byte{byte(i)}) 352 } 353 require.NoError(t, beaconState.SetBlockRoots(blockRoots)) 354 355 aggBits := bitfield.NewBitlist(1) 356 aggBits.SetBitAt(0, true) 357 blockAtt := testutil.HydrateAttestation(ðpb.Attestation{ 358 Data: ðpb.AttestationData{ 359 Slot: beaconState.Slot(), 360 Target: ðpb.Checkpoint{Epoch: helpers.CurrentEpoch(beaconState)}, 361 Source: ðpb.Checkpoint{Root: mockRoot[:]}}, 362 AggregationBits: aggBits, 363 }) 364 365 committee, err := helpers.BeaconCommitteeFromState(beaconState, blockAtt.Data.Slot, blockAtt.Data.CommitteeIndex) 366 assert.NoError(t, err) 367 attestingIndices, err := attestationutil.AttestingIndices(blockAtt.AggregationBits, committee) 368 require.NoError(t, err) 369 assert.NoError(t, err) 370 hashTreeRoot, err = helpers.ComputeSigningRoot(blockAtt.Data, domain) 371 assert.NoError(t, err) 372 sigs := make([]bls.Signature, len(attestingIndices)) 373 for i, indice := range attestingIndices { 374 sig := privKeys[indice].Sign(hashTreeRoot[:]) 375 sigs[i] = sig 376 } 377 blockAtt.Signature = bls.AggregateSignatures(sigs).Marshal() 378 379 exit := ðpb.SignedVoluntaryExit{ 380 Exit: ðpb.VoluntaryExit{ 381 ValidatorIndex: 10, 382 Epoch: 0, 383 }, 384 } 385 exit.Signature, err = helpers.ComputeDomainAndSign(beaconState, currentEpoch, exit.Exit, params.BeaconConfig().DomainVoluntaryExit, privKeys[exit.Exit.ValidatorIndex]) 386 require.NoError(t, err) 387 388 header := beaconState.LatestBlockHeader() 389 prevStateRoot, err := beaconState.HashTreeRoot(context.Background()) 390 require.NoError(t, err) 391 header.StateRoot = prevStateRoot[:] 392 require.NoError(t, beaconState.SetLatestBlockHeader(header)) 393 parentRoot, err := beaconState.LatestBlockHeader().HashTreeRoot() 394 require.NoError(t, err) 395 copied := beaconState.Copy() 396 require.NoError(t, copied.SetSlot(beaconState.Slot()+1)) 397 randaoReveal, err := testutil.RandaoReveal(copied, currentEpoch, privKeys) 398 require.NoError(t, err) 399 proposerIndex, err := helpers.BeaconProposerIndex(copied) 400 require.NoError(t, err) 401 block := testutil.HydrateSignedBeaconBlock(ðpb.SignedBeaconBlock{ 402 Block: ðpb.BeaconBlock{ 403 ParentRoot: parentRoot[:], 404 Slot: beaconState.Slot() + 1, 405 ProposerIndex: proposerIndex, 406 Body: ðpb.BeaconBlockBody{ 407 RandaoReveal: randaoReveal, 408 ProposerSlashings: proposerSlashings, 409 AttesterSlashings: attesterSlashings, 410 Attestations: []*ethpb.Attestation{blockAtt}, 411 VoluntaryExits: []*ethpb.SignedVoluntaryExit{exit}, 412 }, 413 }, 414 }) 415 416 sig, err := testutil.BlockSignature(beaconState, block.Block, privKeys) 417 require.NoError(t, err) 418 block.Signature = sig.Marshal() 419 420 require.NoError(t, beaconState.SetSlot(block.Block.Slot)) 421 return beaconState, block, []*ethpb.Attestation{blockAtt}, proposerSlashings, []*ethpb.SignedVoluntaryExit{exit} 422 } 423 424 func TestProcessBlock_PassesProcessingConditions(t *testing.T) { 425 beaconState, block, _, proposerSlashings, exits := createFullBlockWithOperations(t) 426 exit := exits[0] 427 428 beaconState, err := state.ProcessBlock(context.Background(), beaconState, wrapper.WrappedPhase0SignedBeaconBlock(block)) 429 require.NoError(t, err, "Expected block to pass processing conditions") 430 431 v, err := beaconState.ValidatorAtIndex(proposerSlashings[0].Header_1.Header.ProposerIndex) 432 require.NoError(t, err) 433 assert.Equal(t, true, v.Slashed, "Expected validator at index %d to be slashed", proposerSlashings[0].Header_1.Header.ProposerIndex) 434 v, err = beaconState.ValidatorAtIndex(1) 435 require.NoError(t, err) 436 assert.Equal(t, true, v.Slashed, "Expected validator at index 1 to be slashed, received false") 437 438 v, err = beaconState.ValidatorAtIndex(exit.Exit.ValidatorIndex) 439 require.NoError(t, err) 440 received := v.ExitEpoch 441 wanted := params.BeaconConfig().FarFutureEpoch 442 assert.NotEqual(t, wanted, received, "Expected validator at index %d to be exiting", exit.Exit.ValidatorIndex) 443 } 444 445 func TestProcessEpochPrecompute_CanProcess(t *testing.T) { 446 epoch := types.Epoch(1) 447 448 atts := []*pb.PendingAttestation{{Data: ðpb.AttestationData{Target: ðpb.Checkpoint{Root: make([]byte, 32)}}, InclusionDelay: 1}} 449 slashing := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector) 450 base := &pb.BeaconState{ 451 Slot: params.BeaconConfig().SlotsPerEpoch.Mul(uint64(epoch)) + 1, 452 BlockRoots: make([][]byte, 128), 453 Slashings: slashing, 454 RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector), 455 CurrentEpochAttestations: atts, 456 FinalizedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, 457 JustificationBits: bitfield.Bitvector4{0x00}, 458 CurrentJustifiedCheckpoint: ðpb.Checkpoint{Root: make([]byte, 32)}, 459 } 460 s, err := v1.InitializeFromProto(base) 461 require.NoError(t, err) 462 require.NoError(t, s.SetValidators([]*ethpb.Validator{})) 463 newState, err := state.ProcessEpochPrecompute(context.Background(), s) 464 require.NoError(t, err) 465 assert.Equal(t, uint64(0), newState.Slashings()[2], "Unexpected slashed balance") 466 } 467 468 func BenchmarkProcessBlk_65536Validators_FullBlock(b *testing.B) { 469 logrus.SetLevel(logrus.PanicLevel) 470 471 validatorCount := params.BeaconConfig().MinGenesisActiveValidatorCount * 4 472 committeeCount := validatorCount / params.BeaconConfig().TargetCommitteeSize 473 validators := make([]*ethpb.Validator, validatorCount) 474 for i := 0; i < len(validators); i++ { 475 validators[i] = ðpb.Validator{ 476 EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance, 477 ExitEpoch: params.BeaconConfig().FarFutureEpoch, 478 WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch, 479 ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch, 480 } 481 } 482 validatorBalances := make([]uint64, len(validators)) 483 for i := 0; i < len(validatorBalances); i++ { 484 validatorBalances[i] = params.BeaconConfig().MaxEffectiveBalance 485 } 486 487 randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) 488 for i := 0; i < len(randaoMixes); i++ { 489 randaoMixes[i] = params.BeaconConfig().ZeroHash[:] 490 } 491 492 base := &pb.BeaconState{ 493 Slot: 20, 494 LatestBlockHeader: ðpb.BeaconBlockHeader{}, 495 BlockRoots: make([][]byte, 254), 496 RandaoMixes: randaoMixes, 497 Validators: validators, 498 Balances: validatorBalances, 499 Slashings: make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector), 500 CurrentJustifiedCheckpoint: ðpb.Checkpoint{ 501 Root: []byte("hello-world"), 502 }, 503 Fork: &pb.Fork{ 504 PreviousVersion: []byte{0, 0, 0, 0}, 505 CurrentVersion: []byte{0, 0, 0, 0}, 506 }, 507 } 508 s, err := v1.InitializeFromProto(base) 509 require.NoError(b, err) 510 511 // Set up proposer slashing object for block 512 proposerSlashings := []*ethpb.ProposerSlashing{ 513 { 514 Header_1: ðpb.SignedBeaconBlockHeader{ 515 Header: ðpb.BeaconBlockHeader{ 516 ProposerIndex: 1, 517 Slot: 0, 518 }, 519 Signature: bytesutil.PadTo([]byte("A"), 96), 520 }, 521 Header_2: ðpb.SignedBeaconBlockHeader{ 522 Header: ðpb.BeaconBlockHeader{ 523 ProposerIndex: 1, 524 Slot: 0, 525 }, 526 Signature: bytesutil.PadTo([]byte("B"), 96), 527 }, 528 }, 529 } 530 531 // Set up attester slashing object for block 532 attesterSlashings := []*ethpb.AttesterSlashing{ 533 { 534 Attestation_1: testutil.HydrateIndexedAttestation(ðpb.IndexedAttestation{ 535 AttestingIndices: []uint64{2, 3}, 536 }), 537 Attestation_2: testutil.HydrateIndexedAttestation(ðpb.IndexedAttestation{ 538 AttestingIndices: []uint64{2, 3}, 539 }), 540 }, 541 } 542 543 // Set up deposit object for block 544 deposit := ðpb.Deposit{ 545 Data: ðpb.Deposit_Data{ 546 PublicKey: []byte{1, 2, 3}, 547 Amount: params.BeaconConfig().MaxEffectiveBalance, 548 }, 549 } 550 leaf, err := deposit.Data.HashTreeRoot() 551 require.NoError(b, err) 552 depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth) 553 require.NoError(b, err, "Could not generate trie") 554 proof, err := depositTrie.MerkleProof(0) 555 require.NoError(b, err, "Could not generate proof") 556 deposit.Proof = proof 557 root := depositTrie.Root() 558 559 // Set up randao reveal object for block 560 proposerIdx, err := helpers.BeaconProposerIndex(s) 561 require.NoError(b, err) 562 priv, err := bls.RandKey() 563 require.NoError(b, err) 564 v := s.Validators() 565 v[proposerIdx].PublicKey = priv.PublicKey().Marshal() 566 buf := make([]byte, 32) 567 binary.LittleEndian.PutUint64(buf, 0) 568 domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainRandao, s.GenesisValidatorRoot()) 569 require.NoError(b, err) 570 ctr := &pb.SigningData{ 571 ObjectRoot: buf, 572 Domain: domain, 573 } 574 root, err = ctr.HashTreeRoot() 575 require.NoError(b, err) 576 epochSignature := priv.Sign(root[:]) 577 578 buf = []byte{params.BeaconConfig().BLSWithdrawalPrefixByte} 579 pubKey := []byte("A") 580 hashed := hashutil.Hash(pubKey) 581 buf = append(buf, hashed[:]...) 582 v[3].WithdrawalCredentials = buf 583 584 require.NoError(b, s.SetValidators(v)) 585 586 attestations := make([]*ethpb.Attestation, 128) 587 for i := 0; i < len(attestations); i++ { 588 attestations[i] = ðpb.Attestation{ 589 Data: ðpb.AttestationData{ 590 Source: ðpb.Checkpoint{Root: []byte("hello-world")}}, 591 AggregationBits: bitfield.Bitlist{0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 592 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x01}, 593 } 594 } 595 596 blk := ðpb.SignedBeaconBlock{ 597 Block: ðpb.BeaconBlock{ 598 Slot: s.Slot(), 599 Body: ðpb.BeaconBlockBody{ 600 Eth1Data: ðpb.Eth1Data{ 601 DepositRoot: root[:], 602 BlockHash: root[:], 603 }, 604 RandaoReveal: epochSignature.Marshal(), 605 Attestations: attestations, 606 ProposerSlashings: proposerSlashings, 607 AttesterSlashings: attesterSlashings, 608 }, 609 }, 610 } 611 612 // Precache the shuffled indices 613 for i := uint64(0); i < committeeCount; i++ { 614 _, err := helpers.BeaconCommitteeFromState(s, 0, types.CommitteeIndex(i)) 615 require.NoError(b, err) 616 } 617 618 b.ResetTimer() 619 for n := 0; n < b.N; n++ { 620 _, err := state.ProcessBlock(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(blk)) 621 require.NoError(b, err) 622 // Reset state fields to process block again 623 v := s.Validators() 624 v[1].Slashed = false 625 v[2].Slashed = false 626 require.NoError(b, s.SetValidators(v)) 627 balances := s.Balances() 628 balances[3] += 2 * params.BeaconConfig().MinDepositAmount 629 require.NoError(b, s.SetBalances(balances)) 630 } 631 } 632 633 func TestProcessBlk_AttsBasedOnValidatorCount(t *testing.T) { 634 logrus.SetLevel(logrus.PanicLevel) 635 636 // Default at 256 validators, can raise this number with faster BLS. 637 validatorCount := uint64(256) 638 s, privKeys := testutil.DeterministicGenesisState(t, validatorCount) 639 require.NoError(t, s.SetSlot(params.BeaconConfig().SlotsPerEpoch)) 640 641 bitCount := validatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) 642 aggBits := bitfield.NewBitlist(bitCount) 643 for i := uint64(1); i < bitCount; i++ { 644 aggBits.SetBitAt(i, true) 645 } 646 atts := make([]*ethpb.Attestation, 1) 647 648 for i := 0; i < len(atts); i++ { 649 att := testutil.HydrateAttestation(ðpb.Attestation{ 650 Data: ðpb.AttestationData{Slot: 1}, 651 AggregationBits: aggBits, 652 }) 653 654 committee, err := helpers.BeaconCommitteeFromState(s, att.Data.Slot, att.Data.CommitteeIndex) 655 assert.NoError(t, err) 656 attestingIndices, err := attestationutil.AttestingIndices(att.AggregationBits, committee) 657 require.NoError(t, err) 658 domain, err := helpers.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot()) 659 require.NoError(t, err) 660 sigs := make([]bls.Signature, len(attestingIndices)) 661 for i, indice := range attestingIndices { 662 hashTreeRoot, err := helpers.ComputeSigningRoot(att.Data, domain) 663 assert.NoError(t, err) 664 sig := privKeys[indice].Sign(hashTreeRoot[:]) 665 sigs[i] = sig 666 } 667 att.Signature = bls.AggregateSignatures(sigs).Marshal() 668 atts[i] = att 669 } 670 671 copied := s.Copy() 672 require.NoError(t, copied.SetSlot(s.Slot()+1)) 673 epochSignature, err := testutil.RandaoReveal(copied, helpers.CurrentEpoch(copied), privKeys) 674 require.NoError(t, err) 675 header := s.LatestBlockHeader() 676 prevStateRoot, err := s.HashTreeRoot(context.Background()) 677 require.NoError(t, err) 678 header.StateRoot = prevStateRoot[:] 679 require.NoError(t, s.SetLatestBlockHeader(header)) 680 681 parentRoot, err := s.LatestBlockHeader().HashTreeRoot() 682 require.NoError(t, err) 683 684 nextSlotState := s.Copy() 685 require.NoError(t, nextSlotState.SetSlot(s.Slot()+1)) 686 proposerIdx, err := helpers.BeaconProposerIndex(nextSlotState) 687 require.NoError(t, err) 688 blk := testutil.NewBeaconBlock() 689 blk.Block.ProposerIndex = proposerIdx 690 blk.Block.Slot = s.Slot() + 1 691 blk.Block.ParentRoot = parentRoot[:] 692 blk.Block.Body.RandaoReveal = epochSignature 693 blk.Block.Body.Attestations = atts 694 sig, err := testutil.BlockSignature(s, blk.Block, privKeys) 695 require.NoError(t, err) 696 blk.Signature = sig.Marshal() 697 698 params.SetupTestConfigCleanup(t) 699 config := params.BeaconConfig() 700 config.MinAttestationInclusionDelay = 0 701 params.OverrideBeaconConfig(config) 702 703 require.NoError(t, s.SetSlot(s.Slot()+1)) 704 _, err = state.ProcessBlock(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(blk)) 705 require.NoError(t, err) 706 } 707 708 func TestCanProcessEpoch_TrueOnEpochs(t *testing.T) { 709 tests := []struct { 710 slot types.Slot 711 canProcessEpoch bool 712 }{ 713 { 714 slot: 1, 715 canProcessEpoch: false, 716 }, { 717 slot: 63, 718 canProcessEpoch: true, 719 }, 720 { 721 slot: 64, 722 canProcessEpoch: false, 723 }, { 724 slot: 127, 725 canProcessEpoch: true, 726 }, { 727 slot: 1000000000, 728 canProcessEpoch: false, 729 }, 730 } 731 732 for _, tt := range tests { 733 b := &pb.BeaconState{Slot: tt.slot} 734 s, err := v1.InitializeFromProto(b) 735 require.NoError(t, err) 736 assert.Equal(t, tt.canProcessEpoch, state.CanProcessEpoch(s), "CanProcessEpoch(%d)", tt.slot) 737 } 738 } 739 740 func TestProcessBlock_OverMaxProposerSlashings(t *testing.T) { 741 maxSlashings := params.BeaconConfig().MaxProposerSlashings 742 b := ðpb.SignedBeaconBlock{ 743 Block: ðpb.BeaconBlock{ 744 Body: ðpb.BeaconBlockBody{ 745 ProposerSlashings: make([]*ethpb.ProposerSlashing, maxSlashings+1), 746 }, 747 }, 748 } 749 want := fmt.Sprintf("number of proposer slashings (%d) in block body exceeds allowed threshold of %d", 750 len(b.Block.Body.ProposerSlashings), params.BeaconConfig().MaxProposerSlashings) 751 _, err := state.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b)) 752 assert.ErrorContains(t, want, err) 753 } 754 755 func TestProcessBlock_OverMaxAttesterSlashings(t *testing.T) { 756 maxSlashings := params.BeaconConfig().MaxAttesterSlashings 757 b := ðpb.SignedBeaconBlock{ 758 Block: ðpb.BeaconBlock{ 759 Body: ðpb.BeaconBlockBody{ 760 AttesterSlashings: make([]*ethpb.AttesterSlashing, maxSlashings+1), 761 }, 762 }, 763 } 764 want := fmt.Sprintf("number of attester slashings (%d) in block body exceeds allowed threshold of %d", 765 len(b.Block.Body.AttesterSlashings), params.BeaconConfig().MaxAttesterSlashings) 766 _, err := state.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b)) 767 assert.ErrorContains(t, want, err) 768 } 769 770 func TestProcessBlock_OverMaxAttestations(t *testing.T) { 771 b := ðpb.SignedBeaconBlock{ 772 Block: ðpb.BeaconBlock{ 773 Body: ðpb.BeaconBlockBody{ 774 Attestations: make([]*ethpb.Attestation, params.BeaconConfig().MaxAttestations+1), 775 }, 776 }, 777 } 778 want := fmt.Sprintf("number of attestations (%d) in block body exceeds allowed threshold of %d", 779 len(b.Block.Body.Attestations), params.BeaconConfig().MaxAttestations) 780 _, err := state.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b)) 781 assert.ErrorContains(t, want, err) 782 } 783 784 func TestProcessBlock_OverMaxVoluntaryExits(t *testing.T) { 785 maxExits := params.BeaconConfig().MaxVoluntaryExits 786 b := ðpb.SignedBeaconBlock{ 787 Block: ðpb.BeaconBlock{ 788 Body: ðpb.BeaconBlockBody{ 789 VoluntaryExits: make([]*ethpb.SignedVoluntaryExit, maxExits+1), 790 }, 791 }, 792 } 793 want := fmt.Sprintf("number of voluntary exits (%d) in block body exceeds allowed threshold of %d", 794 len(b.Block.Body.VoluntaryExits), maxExits) 795 _, err := state.VerifyOperationLengths(context.Background(), &v1.BeaconState{}, wrapper.WrappedPhase0SignedBeaconBlock(b)) 796 assert.ErrorContains(t, want, err) 797 } 798 799 func TestProcessBlock_IncorrectDeposits(t *testing.T) { 800 base := &pb.BeaconState{ 801 Eth1Data: ðpb.Eth1Data{DepositCount: 100}, 802 Eth1DepositIndex: 98, 803 } 804 s, err := v1.InitializeFromProto(base) 805 require.NoError(t, err) 806 b := ðpb.SignedBeaconBlock{ 807 Block: ðpb.BeaconBlock{ 808 Body: ðpb.BeaconBlockBody{ 809 Deposits: []*ethpb.Deposit{{}}, 810 }, 811 }, 812 } 813 want := fmt.Sprintf("incorrect outstanding deposits in block body, wanted: %d, got: %d", 814 s.Eth1Data().DepositCount-s.Eth1DepositIndex(), len(b.Block.Body.Deposits)) 815 _, err = state.VerifyOperationLengths(context.Background(), s, wrapper.WrappedPhase0SignedBeaconBlock(b)) 816 assert.ErrorContains(t, want, err) 817 } 818 819 func TestProcessSlots_SameSlotAsParentState(t *testing.T) { 820 slot := types.Slot(2) 821 parentState, err := v1.InitializeFromProto(&pb.BeaconState{Slot: slot}) 822 require.NoError(t, err) 823 824 _, err = state.ProcessSlots(context.Background(), parentState, slot) 825 assert.ErrorContains(t, "expected state.slot 2 < slot 2", err) 826 } 827 828 func TestProcessSlots_LowerSlotAsParentState(t *testing.T) { 829 slot := types.Slot(2) 830 parentState, err := v1.InitializeFromProto(&pb.BeaconState{Slot: slot}) 831 require.NoError(t, err) 832 833 _, err = state.ProcessSlots(context.Background(), parentState, slot-1) 834 assert.ErrorContains(t, "expected state.slot 2 < slot 1", err) 835 } 836 837 func TestProcessSlotsUsingNextSlotCache(t *testing.T) { 838 ctx := context.Background() 839 s, _ := testutil.DeterministicGenesisState(t, 1) 840 r := []byte{'a'} 841 s, err := state.ProcessSlotsUsingNextSlotCache(ctx, s, r, 5) 842 require.NoError(t, err) 843 require.Equal(t, types.Slot(5), s.Slot()) 844 }