github.com/prysmaticlabs/prysm@v1.4.4/shared/testutil/block.go (about) 1 package testutil 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/pkg/errors" 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 v1 "github.com/prysmaticlabs/prysm/proto/eth/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/rand" 17 ) 18 19 // BlockGenConfig is used to define the requested conditions 20 // for block generation. 21 type BlockGenConfig struct { 22 NumProposerSlashings uint64 23 NumAttesterSlashings uint64 24 NumAttestations uint64 25 NumDeposits uint64 26 NumVoluntaryExits uint64 27 } 28 29 // DefaultBlockGenConfig returns the block config that utilizes the 30 // current params in the beacon config. 31 func DefaultBlockGenConfig() *BlockGenConfig { 32 return &BlockGenConfig{ 33 NumProposerSlashings: 0, 34 NumAttesterSlashings: 0, 35 NumAttestations: 1, 36 NumDeposits: 0, 37 NumVoluntaryExits: 0, 38 } 39 } 40 41 // NewBeaconBlock creates a beacon block with minimum marshalable fields. 42 func NewBeaconBlock() *ethpb.SignedBeaconBlock { 43 return ðpb.SignedBeaconBlock{ 44 Block: ðpb.BeaconBlock{ 45 ParentRoot: make([]byte, 32), 46 StateRoot: make([]byte, 32), 47 Body: ðpb.BeaconBlockBody{ 48 RandaoReveal: make([]byte, 96), 49 Eth1Data: ðpb.Eth1Data{ 50 DepositRoot: make([]byte, 32), 51 BlockHash: make([]byte, 32), 52 }, 53 Graffiti: make([]byte, 32), 54 Attestations: []*ethpb.Attestation{}, 55 AttesterSlashings: []*ethpb.AttesterSlashing{}, 56 Deposits: []*ethpb.Deposit{}, 57 ProposerSlashings: []*ethpb.ProposerSlashing{}, 58 VoluntaryExits: []*ethpb.SignedVoluntaryExit{}, 59 }, 60 }, 61 Signature: make([]byte, 96), 62 } 63 } 64 65 // GenerateFullBlock generates a fully valid block with the requested parameters. 66 // Use BlockGenConfig to declare the conditions you would like the block generated under. 67 func GenerateFullBlock( 68 bState iface.BeaconState, 69 privs []bls.SecretKey, 70 conf *BlockGenConfig, 71 slot types.Slot, 72 ) (*ethpb.SignedBeaconBlock, error) { 73 ctx := context.Background() 74 currentSlot := bState.Slot() 75 if currentSlot > slot { 76 return nil, fmt.Errorf("current slot in state is larger than given slot. %d > %d", currentSlot, slot) 77 } 78 bState = bState.Copy() 79 80 if conf == nil { 81 conf = &BlockGenConfig{} 82 } 83 84 var err error 85 var pSlashings []*ethpb.ProposerSlashing 86 numToGen := conf.NumProposerSlashings 87 if numToGen > 0 { 88 pSlashings, err = generateProposerSlashings(bState, privs, numToGen) 89 if err != nil { 90 return nil, errors.Wrapf(err, "failed generating %d proposer slashings:", numToGen) 91 } 92 } 93 94 numToGen = conf.NumAttesterSlashings 95 var aSlashings []*ethpb.AttesterSlashing 96 if numToGen > 0 { 97 aSlashings, err = generateAttesterSlashings(bState, privs, numToGen) 98 if err != nil { 99 return nil, errors.Wrapf(err, "failed generating %d attester slashings:", numToGen) 100 } 101 } 102 103 numToGen = conf.NumAttestations 104 var atts []*ethpb.Attestation 105 if numToGen > 0 { 106 atts, err = GenerateAttestations(bState, privs, numToGen, slot, false) 107 if err != nil { 108 return nil, errors.Wrapf(err, "failed generating %d attestations:", numToGen) 109 } 110 } 111 112 numToGen = conf.NumDeposits 113 var newDeposits []*ethpb.Deposit 114 eth1Data := bState.Eth1Data() 115 if numToGen > 0 { 116 newDeposits, eth1Data, err = generateDepositsAndEth1Data(bState, numToGen) 117 if err != nil { 118 return nil, errors.Wrapf(err, "failed generating %d deposits:", numToGen) 119 } 120 } 121 122 numToGen = conf.NumVoluntaryExits 123 var exits []*ethpb.SignedVoluntaryExit 124 if numToGen > 0 { 125 exits, err = generateVoluntaryExits(bState, privs, numToGen) 126 if err != nil { 127 return nil, errors.Wrapf(err, "failed generating %d attester slashings:", numToGen) 128 } 129 } 130 131 newHeader := bState.LatestBlockHeader() 132 prevStateRoot, err := bState.HashTreeRoot(ctx) 133 if err != nil { 134 return nil, err 135 } 136 newHeader.StateRoot = prevStateRoot[:] 137 parentRoot, err := newHeader.HashTreeRoot() 138 if err != nil { 139 return nil, err 140 } 141 142 if slot == currentSlot { 143 slot = currentSlot + 1 144 } 145 146 // Temporarily incrementing the beacon state slot here since BeaconProposerIndex is a 147 // function deterministic on beacon state slot. 148 if err := bState.SetSlot(slot); err != nil { 149 return nil, err 150 } 151 reveal, err := RandaoReveal(bState, helpers.CurrentEpoch(bState), privs) 152 if err != nil { 153 return nil, err 154 } 155 156 idx, err := helpers.BeaconProposerIndex(bState) 157 if err != nil { 158 return nil, err 159 } 160 161 block := ðpb.BeaconBlock{ 162 Slot: slot, 163 ParentRoot: parentRoot[:], 164 ProposerIndex: idx, 165 Body: ðpb.BeaconBlockBody{ 166 Eth1Data: eth1Data, 167 RandaoReveal: reveal, 168 ProposerSlashings: pSlashings, 169 AttesterSlashings: aSlashings, 170 Attestations: atts, 171 VoluntaryExits: exits, 172 Deposits: newDeposits, 173 Graffiti: make([]byte, 32), 174 }, 175 } 176 if err := bState.SetSlot(currentSlot); err != nil { 177 return nil, err 178 } 179 180 signature, err := BlockSignature(bState, block, privs) 181 if err != nil { 182 return nil, err 183 } 184 185 return ðpb.SignedBeaconBlock{Block: block, Signature: signature.Marshal()}, nil 186 } 187 188 // GenerateProposerSlashingForValidator for a specific validator index. 189 func GenerateProposerSlashingForValidator( 190 bState iface.BeaconState, 191 priv bls.SecretKey, 192 idx types.ValidatorIndex, 193 ) (*ethpb.ProposerSlashing, error) { 194 header1 := HydrateSignedBeaconHeader(ðpb.SignedBeaconBlockHeader{ 195 Header: ðpb.BeaconBlockHeader{ 196 ProposerIndex: idx, 197 Slot: bState.Slot(), 198 BodyRoot: bytesutil.PadTo([]byte{0, 1, 0}, 32), 199 }, 200 }) 201 currentEpoch := helpers.CurrentEpoch(bState) 202 var err error 203 header1.Signature, err = helpers.ComputeDomainAndSign(bState, currentEpoch, header1.Header, params.BeaconConfig().DomainBeaconProposer, priv) 204 if err != nil { 205 return nil, err 206 } 207 208 header2 := ðpb.SignedBeaconBlockHeader{ 209 Header: ðpb.BeaconBlockHeader{ 210 ProposerIndex: idx, 211 Slot: bState.Slot(), 212 BodyRoot: bytesutil.PadTo([]byte{0, 2, 0}, 32), 213 StateRoot: make([]byte, 32), 214 ParentRoot: make([]byte, 32), 215 }, 216 } 217 header2.Signature, err = helpers.ComputeDomainAndSign(bState, currentEpoch, header2.Header, params.BeaconConfig().DomainBeaconProposer, priv) 218 if err != nil { 219 return nil, err 220 } 221 222 return ðpb.ProposerSlashing{ 223 Header_1: header1, 224 Header_2: header2, 225 }, nil 226 } 227 228 func generateProposerSlashings( 229 bState iface.BeaconState, 230 privs []bls.SecretKey, 231 numSlashings uint64, 232 ) ([]*ethpb.ProposerSlashing, error) { 233 proposerSlashings := make([]*ethpb.ProposerSlashing, numSlashings) 234 for i := uint64(0); i < numSlashings; i++ { 235 proposerIndex, err := randValIndex(bState) 236 if err != nil { 237 return nil, err 238 } 239 slashing, err := GenerateProposerSlashingForValidator(bState, privs[proposerIndex], proposerIndex) 240 if err != nil { 241 return nil, err 242 } 243 proposerSlashings[i] = slashing 244 } 245 return proposerSlashings, nil 246 } 247 248 // GenerateAttesterSlashingForValidator for a specific validator index. 249 func GenerateAttesterSlashingForValidator( 250 bState iface.BeaconState, 251 priv bls.SecretKey, 252 idx types.ValidatorIndex, 253 ) (*ethpb.AttesterSlashing, error) { 254 currentEpoch := helpers.CurrentEpoch(bState) 255 256 att1 := ðpb.IndexedAttestation{ 257 Data: ðpb.AttestationData{ 258 Slot: bState.Slot(), 259 CommitteeIndex: 0, 260 BeaconBlockRoot: make([]byte, 32), 261 Target: ðpb.Checkpoint{ 262 Epoch: currentEpoch, 263 Root: params.BeaconConfig().ZeroHash[:], 264 }, 265 Source: ðpb.Checkpoint{ 266 Epoch: currentEpoch + 1, 267 Root: params.BeaconConfig().ZeroHash[:], 268 }, 269 }, 270 AttestingIndices: []uint64{uint64(idx)}, 271 } 272 var err error 273 att1.Signature, err = helpers.ComputeDomainAndSign(bState, currentEpoch, att1.Data, params.BeaconConfig().DomainBeaconAttester, priv) 274 if err != nil { 275 return nil, err 276 } 277 278 att2 := ðpb.IndexedAttestation{ 279 Data: ðpb.AttestationData{ 280 Slot: bState.Slot(), 281 CommitteeIndex: 0, 282 BeaconBlockRoot: make([]byte, 32), 283 Target: ðpb.Checkpoint{ 284 Epoch: currentEpoch, 285 Root: params.BeaconConfig().ZeroHash[:], 286 }, 287 Source: ðpb.Checkpoint{ 288 Epoch: currentEpoch, 289 Root: params.BeaconConfig().ZeroHash[:], 290 }, 291 }, 292 AttestingIndices: []uint64{uint64(idx)}, 293 } 294 att2.Signature, err = helpers.ComputeDomainAndSign(bState, currentEpoch, att2.Data, params.BeaconConfig().DomainBeaconAttester, priv) 295 if err != nil { 296 return nil, err 297 } 298 299 return ðpb.AttesterSlashing{ 300 Attestation_1: att1, 301 Attestation_2: att2, 302 }, nil 303 } 304 305 func generateAttesterSlashings( 306 bState iface.BeaconState, 307 privs []bls.SecretKey, 308 numSlashings uint64, 309 ) ([]*ethpb.AttesterSlashing, error) { 310 attesterSlashings := make([]*ethpb.AttesterSlashing, numSlashings) 311 randGen := rand.NewDeterministicGenerator() 312 for i := uint64(0); i < numSlashings; i++ { 313 committeeIndex := randGen.Uint64() % params.BeaconConfig().MaxCommitteesPerSlot 314 committee, err := helpers.BeaconCommitteeFromState(bState, bState.Slot(), types.CommitteeIndex(committeeIndex)) 315 if err != nil { 316 return nil, err 317 } 318 randIndex := randGen.Uint64() % uint64(len(committee)) 319 valIndex := committee[randIndex] 320 slashing, err := GenerateAttesterSlashingForValidator(bState, privs[valIndex], valIndex) 321 if err != nil { 322 return nil, err 323 } 324 attesterSlashings[i] = slashing 325 } 326 return attesterSlashings, nil 327 } 328 329 func generateDepositsAndEth1Data( 330 bState iface.BeaconState, 331 numDeposits uint64, 332 ) ( 333 []*ethpb.Deposit, 334 *ethpb.Eth1Data, 335 error, 336 ) { 337 previousDepsLen := bState.Eth1DepositIndex() 338 currentDeposits, _, err := DeterministicDepositsAndKeys(previousDepsLen + numDeposits) 339 if err != nil { 340 return nil, nil, errors.Wrap(err, "could not get deposits") 341 } 342 eth1Data, err := DeterministicEth1Data(len(currentDeposits)) 343 if err != nil { 344 return nil, nil, errors.Wrap(err, "could not get eth1data") 345 } 346 return currentDeposits[previousDepsLen:], eth1Data, nil 347 } 348 349 func generateVoluntaryExits( 350 bState iface.BeaconState, 351 privs []bls.SecretKey, 352 numExits uint64, 353 ) ([]*ethpb.SignedVoluntaryExit, error) { 354 currentEpoch := helpers.CurrentEpoch(bState) 355 356 voluntaryExits := make([]*ethpb.SignedVoluntaryExit, numExits) 357 for i := 0; i < len(voluntaryExits); i++ { 358 valIndex, err := randValIndex(bState) 359 if err != nil { 360 return nil, err 361 } 362 exit := ðpb.SignedVoluntaryExit{ 363 Exit: ðpb.VoluntaryExit{ 364 Epoch: helpers.PrevEpoch(bState), 365 ValidatorIndex: valIndex, 366 }, 367 } 368 exit.Signature, err = helpers.ComputeDomainAndSign(bState, currentEpoch, exit.Exit, params.BeaconConfig().DomainVoluntaryExit, privs[valIndex]) 369 if err != nil { 370 return nil, err 371 } 372 voluntaryExits[i] = exit 373 } 374 return voluntaryExits, nil 375 } 376 377 func randValIndex(bState iface.BeaconState) (types.ValidatorIndex, error) { 378 activeCount, err := helpers.ActiveValidatorCount(bState, helpers.CurrentEpoch(bState)) 379 if err != nil { 380 return 0, err 381 } 382 return types.ValidatorIndex(rand.NewGenerator().Uint64() % activeCount), nil 383 } 384 385 // HydrateSignedBeaconHeader hydrates a signed beacon block header with correct field length sizes 386 // to comply with fssz marshalling and unmarshalling rules. 387 func HydrateSignedBeaconHeader(h *ethpb.SignedBeaconBlockHeader) *ethpb.SignedBeaconBlockHeader { 388 if h.Signature == nil { 389 h.Signature = make([]byte, params.BeaconConfig().BLSSignatureLength) 390 } 391 h.Header = HydrateBeaconHeader(h.Header) 392 return h 393 } 394 395 // HydrateBeaconHeader hydrates a beacon block header with correct field length sizes 396 // to comply with fssz marshalling and unmarshalling rules. 397 func HydrateBeaconHeader(h *ethpb.BeaconBlockHeader) *ethpb.BeaconBlockHeader { 398 if h == nil { 399 h = ðpb.BeaconBlockHeader{} 400 } 401 if h.BodyRoot == nil { 402 h.BodyRoot = make([]byte, 32) 403 } 404 if h.StateRoot == nil { 405 h.StateRoot = make([]byte, 32) 406 } 407 if h.ParentRoot == nil { 408 h.ParentRoot = make([]byte, 32) 409 } 410 return h 411 } 412 413 // HydrateSignedBeaconBlock hydrates a signed beacon block with correct field length sizes 414 // to comply with fssz marshalling and unmarshalling rules. 415 func HydrateSignedBeaconBlock(b *ethpb.SignedBeaconBlock) *ethpb.SignedBeaconBlock { 416 if b.Signature == nil { 417 b.Signature = make([]byte, params.BeaconConfig().BLSSignatureLength) 418 } 419 b.Block = HydrateBeaconBlock(b.Block) 420 return b 421 } 422 423 // HydrateBeaconBlock hydrates a beacon block with correct field length sizes 424 // to comply with fssz marshalling and unmarshalling rules. 425 func HydrateBeaconBlock(b *ethpb.BeaconBlock) *ethpb.BeaconBlock { 426 if b == nil { 427 b = ðpb.BeaconBlock{} 428 } 429 if b.ParentRoot == nil { 430 b.ParentRoot = make([]byte, 32) 431 } 432 if b.StateRoot == nil { 433 b.StateRoot = make([]byte, 32) 434 } 435 b.Body = HydrateBeaconBlockBody(b.Body) 436 return b 437 } 438 439 // HydrateBeaconBlockBody hydrates a beacon block body with correct field length sizes 440 // to comply with fssz marshalling and unmarshalling rules. 441 func HydrateBeaconBlockBody(b *ethpb.BeaconBlockBody) *ethpb.BeaconBlockBody { 442 if b == nil { 443 b = ðpb.BeaconBlockBody{} 444 } 445 if b.RandaoReveal == nil { 446 b.RandaoReveal = make([]byte, params.BeaconConfig().BLSSignatureLength) 447 } 448 if b.Graffiti == nil { 449 b.Graffiti = make([]byte, 32) 450 } 451 if b.Eth1Data == nil { 452 b.Eth1Data = ðpb.Eth1Data{ 453 DepositRoot: make([]byte, 32), 454 BlockHash: make([]byte, 32), 455 } 456 } 457 return b 458 } 459 460 // HydrateV1SignedBeaconBlock hydrates a signed beacon block with correct field length sizes 461 // to comply with fssz marshalling and unmarshalling rules. 462 func HydrateV1SignedBeaconBlock(b *v1.SignedBeaconBlock) *v1.SignedBeaconBlock { 463 if b.Signature == nil { 464 b.Signature = make([]byte, params.BeaconConfig().BLSSignatureLength) 465 } 466 b.Block = HydrateV1BeaconBlock(b.Block) 467 return b 468 } 469 470 // HydrateV1BeaconBlock hydrates a beacon block with correct field length sizes 471 // to comply with fssz marshalling and unmarshalling rules. 472 func HydrateV1BeaconBlock(b *v1.BeaconBlock) *v1.BeaconBlock { 473 if b == nil { 474 b = &v1.BeaconBlock{} 475 } 476 if b.ParentRoot == nil { 477 b.ParentRoot = make([]byte, 32) 478 } 479 if b.StateRoot == nil { 480 b.StateRoot = make([]byte, 32) 481 } 482 b.Body = HydrateV1BeaconBlockBody(b.Body) 483 return b 484 } 485 486 // HydrateV1BeaconBlockBody hydrates a beacon block body with correct field length sizes 487 // to comply with fssz marshalling and unmarshalling rules. 488 func HydrateV1BeaconBlockBody(b *v1.BeaconBlockBody) *v1.BeaconBlockBody { 489 if b == nil { 490 b = &v1.BeaconBlockBody{} 491 } 492 if b.RandaoReveal == nil { 493 b.RandaoReveal = make([]byte, params.BeaconConfig().BLSSignatureLength) 494 } 495 if b.Graffiti == nil { 496 b.Graffiti = make([]byte, 32) 497 } 498 if b.Eth1Data == nil { 499 b.Eth1Data = &v1.Eth1Data{ 500 DepositRoot: make([]byte, 32), 501 BlockHash: make([]byte, 32), 502 } 503 } 504 return b 505 }