github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/utils/unittest/fixtures.go (about) 1 package unittest 2 3 import ( 4 "bytes" 5 crand "crypto/rand" 6 "fmt" 7 "math/rand" 8 "net" 9 "testing" 10 "time" 11 12 "github.com/ipfs/go-cid" 13 pubsub "github.com/libp2p/go-libp2p-pubsub" 14 pubsub_pb "github.com/libp2p/go-libp2p-pubsub/pb" 15 "github.com/libp2p/go-libp2p/core/peer" 16 "github.com/onflow/cadence" 17 "github.com/onflow/crypto" 18 "github.com/onflow/crypto/hash" 19 "github.com/stretchr/testify/require" 20 21 sdk "github.com/onflow/flow-go-sdk" 22 hotstuff "github.com/onflow/flow-go/consensus/hotstuff/model" 23 "github.com/onflow/flow-go/engine" 24 "github.com/onflow/flow-go/engine/access/rest/util" 25 "github.com/onflow/flow-go/fvm/storage/snapshot" 26 "github.com/onflow/flow-go/ledger" 27 "github.com/onflow/flow-go/ledger/common/bitutils" 28 "github.com/onflow/flow-go/ledger/common/testutils" 29 "github.com/onflow/flow-go/model/bootstrap" 30 "github.com/onflow/flow-go/model/chainsync" 31 "github.com/onflow/flow-go/model/chunks" 32 "github.com/onflow/flow-go/model/cluster" 33 "github.com/onflow/flow-go/model/encoding" 34 "github.com/onflow/flow-go/model/flow" 35 "github.com/onflow/flow-go/model/flow/filter" 36 "github.com/onflow/flow-go/model/flow/mapfunc" 37 "github.com/onflow/flow-go/model/messages" 38 "github.com/onflow/flow-go/model/verification" 39 "github.com/onflow/flow-go/module" 40 "github.com/onflow/flow-go/module/executiondatasync/execution_data" 41 "github.com/onflow/flow-go/module/mempool/entity" 42 "github.com/onflow/flow-go/module/signature" 43 "github.com/onflow/flow-go/module/updatable_configs" 44 "github.com/onflow/flow-go/network/channels" 45 "github.com/onflow/flow-go/network/message" 46 p2pconfig "github.com/onflow/flow-go/network/p2p/config" 47 "github.com/onflow/flow-go/network/p2p/keyutils" 48 "github.com/onflow/flow-go/state/protocol" 49 "github.com/onflow/flow-go/state/protocol/inmem" 50 "github.com/onflow/flow-go/state/protocol/protocol_state/kvstore" 51 "github.com/onflow/flow-go/utils/dsl" 52 ) 53 54 const ( 55 DefaultSeedFixtureLength = 64 56 DefaultAddress = "localhost:0" 57 ) 58 59 // returns a deterministic math/rand PRG that can be used for deterministic randomness in tests only. 60 // The PRG seed is logged in case the test iteration needs to be reproduced. 61 func GetPRG(t *testing.T) *rand.Rand { 62 random := time.Now().UnixNano() 63 t.Logf("rng seed is %d", random) 64 rng := rand.New(rand.NewSource(random)) 65 return rng 66 } 67 68 func IPPort(port string) string { 69 return net.JoinHostPort("localhost", port) 70 } 71 72 func AddressFixture() flow.Address { 73 return flow.Testnet.Chain().ServiceAddress() 74 } 75 76 func RandomAddressFixture() flow.Address { 77 return RandomAddressFixtureForChain(flow.Testnet) 78 } 79 80 func RandomAddressFixtureForChain(chainID flow.ChainID) flow.Address { 81 // we use a 32-bit index - since the linear address generator uses 45 bits, 82 // this won't error 83 addr, err := chainID.Chain().AddressAtIndex(uint64(rand.Uint32())) 84 if err != nil { 85 panic(err) 86 } 87 return addr 88 } 89 90 // Uint64InRange returns a uint64 value drawn from the uniform random distribution [min,max]. 91 func Uint64InRange(min, max uint64) uint64 { 92 return min + uint64(rand.Intn(int(max)+1-int(min))) 93 } 94 95 func RandomSDKAddressFixture() sdk.Address { 96 addr := RandomAddressFixture() 97 var sdkAddr sdk.Address 98 copy(sdkAddr[:], addr[:]) 99 return sdkAddr 100 } 101 102 func InvalidAddressFixture() flow.Address { 103 addr := AddressFixture() 104 addr[0] ^= 1 // alter one bit to obtain an invalid address 105 if flow.Testnet.Chain().IsValid(addr) { 106 panic("invalid address fixture generated valid address") 107 } 108 return addr 109 } 110 111 func InvalidFormatSignature() flow.TransactionSignature { 112 return flow.TransactionSignature{ 113 Address: AddressFixture(), 114 SignerIndex: 0, 115 Signature: make([]byte, crypto.SignatureLenECDSAP256), // zero signature is invalid 116 KeyIndex: 1, 117 } 118 } 119 120 func TransactionSignatureFixture() flow.TransactionSignature { 121 sigLen := crypto.SignatureLenECDSAP256 122 s := flow.TransactionSignature{ 123 Address: AddressFixture(), 124 SignerIndex: 0, 125 Signature: SeedFixture(sigLen), 126 KeyIndex: 1, 127 } 128 // make sure the ECDSA signature passes the format check 129 s.Signature[sigLen/2] = 0 130 s.Signature[0] = 0 131 s.Signature[sigLen/2-1] |= 1 132 s.Signature[sigLen-1] |= 1 133 return s 134 } 135 136 func ProposalKeyFixture() flow.ProposalKey { 137 return flow.ProposalKey{ 138 Address: AddressFixture(), 139 KeyIndex: 1, 140 SequenceNumber: 0, 141 } 142 } 143 144 // AccountKeyDefaultFixture returns a randomly generated ECDSA/SHA3 account key. 145 func AccountKeyDefaultFixture() (*flow.AccountPrivateKey, error) { 146 return AccountKeyFixture(crypto.KeyGenSeedMinLen, crypto.ECDSAP256, hash.SHA3_256) 147 } 148 149 // AccountKeyFixture returns a randomly generated account key. 150 func AccountKeyFixture( 151 seedLength int, 152 signingAlgo crypto.SigningAlgorithm, 153 hashAlgo hash.HashingAlgorithm, 154 ) (*flow.AccountPrivateKey, error) { 155 seed := make([]byte, seedLength) 156 157 _, err := crand.Read(seed) 158 if err != nil { 159 return nil, err 160 } 161 162 key, err := crypto.GeneratePrivateKey(signingAlgo, seed) 163 if err != nil { 164 return nil, err 165 } 166 167 return &flow.AccountPrivateKey{ 168 PrivateKey: key, 169 SignAlgo: key.Algorithm(), 170 HashAlgo: hashAlgo, 171 }, nil 172 } 173 174 // AccountFixture returns a randomly generated account. 175 func AccountFixture() (*flow.Account, error) { 176 key, err := AccountKeyFixture(128, crypto.ECDSAP256, hash.SHA3_256) 177 if err != nil { 178 return nil, err 179 } 180 181 contracts := make(map[string][]byte, 2) 182 contracts["contract1"] = []byte("contract1") 183 contracts["contract2"] = []byte("contract2") 184 185 return &flow.Account{ 186 Address: RandomAddressFixture(), 187 Balance: 100, 188 Keys: []flow.AccountPublicKey{key.PublicKey(1000)}, 189 Contracts: contracts, 190 }, nil 191 } 192 193 func BlockFixture() flow.Block { 194 header := BlockHeaderFixture() 195 return *BlockWithParentFixture(header) 196 } 197 198 func ChainBlockFixture(n int) []*flow.Block { 199 root := BlockHeaderFixture() 200 return ChainBlockFixtureWithRoot(root, n) 201 } 202 203 func ChainBlockFixtureWithRoot(root *flow.Header, n int) []*flow.Block { 204 bs := make([]*flow.Block, 0, n) 205 parent := root 206 for i := 0; i < n; i++ { 207 b := BlockWithParentFixture(parent) 208 bs = append(bs, b) 209 parent = b.Header 210 } 211 return bs 212 } 213 214 func RechainBlocks(blocks []*flow.Block) { 215 if len(blocks) == 0 { 216 return 217 } 218 219 parent := blocks[0] 220 221 for _, block := range blocks[1:] { 222 block.Header.ParentID = parent.ID() 223 parent = block 224 } 225 } 226 227 func FullBlockFixture() flow.Block { 228 block := BlockFixture() 229 payload := block.Payload 230 payload.Seals = Seal.Fixtures(10) 231 payload.Results = []*flow.ExecutionResult{ 232 ExecutionResultFixture(), 233 ExecutionResultFixture(), 234 } 235 payload.Receipts = []*flow.ExecutionReceiptMeta{ 236 ExecutionReceiptFixture(WithResult(payload.Results[0])).Meta(), 237 ExecutionReceiptFixture(WithResult(payload.Results[1])).Meta(), 238 } 239 payload.ProtocolStateID = IdentifierFixture() 240 241 header := block.Header 242 header.PayloadHash = payload.Hash() 243 244 return flow.Block{ 245 Header: header, 246 Payload: payload, 247 } 248 } 249 250 func BlockFixtures(number int) []*flow.Block { 251 blocks := make([]*flow.Block, 0, number) 252 for ; number > 0; number-- { 253 block := BlockFixture() 254 blocks = append(blocks, &block) 255 } 256 return blocks 257 } 258 259 func ProposalFixture() *messages.BlockProposal { 260 block := BlockFixture() 261 return ProposalFromBlock(&block) 262 } 263 264 func ProposalFromBlock(block *flow.Block) *messages.BlockProposal { 265 return messages.NewBlockProposal(block) 266 } 267 268 func ClusterProposalFromBlock(block *cluster.Block) *messages.ClusterBlockProposal { 269 return messages.NewClusterBlockProposal(block) 270 } 271 272 func BlockchainFixture(length int) []*flow.Block { 273 blocks := make([]*flow.Block, length) 274 275 genesis := BlockFixture() 276 blocks[0] = &genesis 277 for i := 1; i < length; i++ { 278 blocks[i] = BlockWithParentFixture(blocks[i-1].Header) 279 } 280 281 return blocks 282 } 283 284 // AsSlashable returns the input message T, wrapped as a flow.Slashable instance with a random origin ID. 285 func AsSlashable[T any](msg T) flow.Slashable[T] { 286 slashable := flow.Slashable[T]{ 287 OriginID: IdentifierFixture(), 288 Message: msg, 289 } 290 return slashable 291 } 292 293 func ReceiptAndSealForBlock(block *flow.Block) (*flow.ExecutionReceipt, *flow.Seal) { 294 receipt := ReceiptForBlockFixture(block) 295 seal := Seal.Fixture(Seal.WithBlock(block.Header), Seal.WithResult(&receipt.ExecutionResult)) 296 return receipt, seal 297 } 298 299 func PayloadFixture(options ...func(*flow.Payload)) flow.Payload { 300 payload := flow.EmptyPayload() 301 for _, option := range options { 302 option(&payload) 303 } 304 return payload 305 } 306 307 // WithAllTheFixins ensures a payload contains no empty slice fields. When 308 // encoding and decoding, nil vs empty slices are not preserved, which can 309 // result in two models that are semantically equal being considered non-equal 310 // by our testing framework. 311 func WithAllTheFixins(payload *flow.Payload) { 312 payload.Seals = Seal.Fixtures(3) 313 payload.Guarantees = CollectionGuaranteesFixture(4) 314 for i := 0; i < 10; i++ { 315 receipt := ExecutionReceiptFixture( 316 WithResult(ExecutionResultFixture(WithServiceEvents(3))), 317 WithSpocks(SignaturesFixture(3)), 318 ) 319 payload.Receipts = flow.ExecutionReceiptMetaList{receipt.Meta()} 320 payload.Results = flow.ExecutionResultList{&receipt.ExecutionResult} 321 } 322 payload.ProtocolStateID = IdentifierFixture() 323 } 324 325 func WithSeals(seals ...*flow.Seal) func(*flow.Payload) { 326 return func(payload *flow.Payload) { 327 payload.Seals = append(payload.Seals, seals...) 328 } 329 } 330 331 func WithGuarantees(guarantees ...*flow.CollectionGuarantee) func(*flow.Payload) { 332 return func(payload *flow.Payload) { 333 payload.Guarantees = append(payload.Guarantees, guarantees...) 334 } 335 } 336 337 func WithReceipts(receipts ...*flow.ExecutionReceipt) func(*flow.Payload) { 338 return func(payload *flow.Payload) { 339 for _, receipt := range receipts { 340 payload.Receipts = append(payload.Receipts, receipt.Meta()) 341 payload.Results = append(payload.Results, &receipt.ExecutionResult) 342 } 343 } 344 } 345 346 func WithProtocolStateID(stateID flow.Identifier) func(payload *flow.Payload) { 347 return func(payload *flow.Payload) { 348 payload.ProtocolStateID = stateID 349 } 350 } 351 352 // WithReceiptsAndNoResults will add receipt to payload only 353 func WithReceiptsAndNoResults(receipts ...*flow.ExecutionReceipt) func(*flow.Payload) { 354 return func(payload *flow.Payload) { 355 for _, receipt := range receipts { 356 payload.Receipts = append(payload.Receipts, receipt.Meta()) 357 } 358 } 359 } 360 361 // WithExecutionResults will add execution results to payload 362 func WithExecutionResults(results ...*flow.ExecutionResult) func(*flow.Payload) { 363 return func(payload *flow.Payload) { 364 for _, result := range results { 365 payload.Results = append(payload.Results, result) 366 } 367 } 368 } 369 370 func BlockWithParentFixture(parent *flow.Header) *flow.Block { 371 payload := PayloadFixture() 372 header := BlockHeaderWithParentFixture(parent) 373 header.PayloadHash = payload.Hash() 374 return &flow.Block{ 375 Header: header, 376 Payload: &payload, 377 } 378 } 379 380 func BlockWithParentProtocolState(parent *flow.Block) *flow.Block { 381 payload := PayloadFixture(WithProtocolStateID(parent.Payload.ProtocolStateID)) 382 header := BlockHeaderWithParentFixture(parent.Header) 383 header.PayloadHash = payload.Hash() 384 return &flow.Block{ 385 Header: header, 386 Payload: &payload, 387 } 388 } 389 390 func BlockWithGuaranteesFixture(guarantees []*flow.CollectionGuarantee) *flow.Block { 391 payload := PayloadFixture(WithGuarantees(guarantees...)) 392 header := BlockHeaderFixture() 393 header.PayloadHash = payload.Hash() 394 return &flow.Block{ 395 Header: header, 396 Payload: &payload, 397 } 398 399 } 400 401 func WithoutGuarantee(payload *flow.Payload) { 402 payload.Guarantees = nil 403 } 404 405 func StateInteractionsFixture() *snapshot.ExecutionSnapshot { 406 return &snapshot.ExecutionSnapshot{} 407 } 408 409 func BlockWithParentAndProposerFixture( 410 t *testing.T, 411 parent *flow.Header, 412 proposer flow.Identifier, 413 ) flow.Block { 414 block := BlockWithParentFixture(parent) 415 416 indices, err := signature.EncodeSignersToIndices( 417 []flow.Identifier{proposer}, []flow.Identifier{proposer}) 418 require.NoError(t, err) 419 420 block.Header.ProposerID = proposer 421 block.Header.ParentVoterIndices = indices 422 if block.Header.LastViewTC != nil { 423 block.Header.LastViewTC.SignerIndices = indices 424 block.Header.LastViewTC.NewestQC.SignerIndices = indices 425 } 426 427 return *block 428 } 429 430 func BlockWithParentAndSeals(parent *flow.Header, seals []*flow.Header) *flow.Block { 431 block := BlockWithParentFixture(parent) 432 payload := flow.Payload{ 433 Guarantees: nil, 434 } 435 436 if len(seals) > 0 { 437 payload.Seals = make([]*flow.Seal, len(seals)) 438 for i, seal := range seals { 439 payload.Seals[i] = Seal.Fixture( 440 Seal.WithBlockID(seal.ID()), 441 ) 442 } 443 } 444 445 block.SetPayload(payload) 446 return block 447 } 448 449 func GenesisFixture() *flow.Block { 450 genesis := flow.Genesis(flow.Emulator) 451 return genesis 452 } 453 454 func WithHeaderHeight(height uint64) func(header *flow.Header) { 455 return func(header *flow.Header) { 456 header.Height = height 457 } 458 } 459 460 func HeaderWithView(view uint64) func(*flow.Header) { 461 return func(header *flow.Header) { 462 header.View = view 463 } 464 } 465 466 func BlockHeaderFixture(opts ...func(header *flow.Header)) *flow.Header { 467 height := 1 + uint64(rand.Uint32()) // avoiding edge case of height = 0 (genesis block) 468 view := height + uint64(rand.Intn(1000)) 469 header := BlockHeaderWithParentFixture(&flow.Header{ 470 ChainID: flow.Emulator, 471 ParentID: IdentifierFixture(), 472 Height: height, 473 View: view, 474 }) 475 476 for _, opt := range opts { 477 opt(header) 478 } 479 480 return header 481 } 482 483 func BlockHeaderFixtureOnChain( 484 chainID flow.ChainID, 485 opts ...func(header *flow.Header), 486 ) *flow.Header { 487 height := 1 + uint64(rand.Uint32()) // avoiding edge case of height = 0 (genesis block) 488 view := height + uint64(rand.Intn(1000)) 489 header := BlockHeaderWithParentFixture(&flow.Header{ 490 ChainID: chainID, 491 ParentID: IdentifierFixture(), 492 Height: height, 493 View: view, 494 }) 495 496 for _, opt := range opts { 497 opt(header) 498 } 499 500 return header 501 } 502 503 func BlockHeaderWithParentFixture(parent *flow.Header) *flow.Header { 504 height := parent.Height + 1 505 view := parent.View + 1 + uint64(rand.Intn(10)) // Intn returns [0, n) 506 var lastViewTC *flow.TimeoutCertificate 507 if view != parent.View+1 { 508 newestQC := QuorumCertificateFixture(func(qc *flow.QuorumCertificate) { 509 qc.View = parent.View 510 }) 511 lastViewTC = &flow.TimeoutCertificate{ 512 View: view - 1, 513 NewestQCViews: []uint64{newestQC.View}, 514 NewestQC: newestQC, 515 SignerIndices: SignerIndicesFixture(4), 516 SigData: SignatureFixture(), 517 } 518 } 519 return &flow.Header{ 520 ChainID: parent.ChainID, 521 ParentID: parent.ID(), 522 Height: height, 523 PayloadHash: IdentifierFixture(), 524 Timestamp: time.Now().UTC(), 525 View: view, 526 ParentView: parent.View, 527 ParentVoterIndices: SignerIndicesFixture(4), 528 ParentVoterSigData: QCSigDataFixture(), 529 ProposerID: IdentifierFixture(), 530 ProposerSigData: SignatureFixture(), 531 LastViewTC: lastViewTC, 532 } 533 } 534 535 func BlockHeaderWithHeight(height uint64) *flow.Header { 536 return BlockHeaderFixture(WithHeaderHeight(height)) 537 } 538 539 func BlockHeaderWithParentWithSoRFixture(parent *flow.Header, source []byte) *flow.Header { 540 height := parent.Height + 1 541 view := parent.View + 1 + uint64(rand.Intn(10)) // Intn returns [0, n) 542 var lastViewTC *flow.TimeoutCertificate 543 if view != parent.View+1 { 544 newestQC := QuorumCertificateFixture(func(qc *flow.QuorumCertificate) { 545 qc.View = parent.View 546 }) 547 lastViewTC = &flow.TimeoutCertificate{ 548 View: view - 1, 549 NewestQCViews: []uint64{newestQC.View}, 550 NewestQC: newestQC, 551 SignerIndices: SignerIndicesFixture(4), 552 SigData: SignatureFixture(), 553 } 554 } 555 return &flow.Header{ 556 ChainID: parent.ChainID, 557 ParentID: parent.ID(), 558 Height: height, 559 PayloadHash: IdentifierFixture(), 560 Timestamp: time.Now().UTC(), 561 View: view, 562 ParentView: parent.View, 563 ParentVoterIndices: SignerIndicesFixture(4), 564 ParentVoterSigData: QCSigDataWithSoRFixture(source), 565 ProposerID: IdentifierFixture(), 566 ProposerSigData: SignatureFixture(), 567 LastViewTC: lastViewTC, 568 } 569 } 570 571 func ClusterPayloadFixture(n int) *cluster.Payload { 572 transactions := make([]*flow.TransactionBody, n) 573 for i := 0; i < n; i++ { 574 tx := TransactionBodyFixture() 575 transactions[i] = &tx 576 } 577 payload := cluster.PayloadFromTransactions(flow.ZeroID, transactions...) 578 return &payload 579 } 580 581 func ClusterBlockFixture() cluster.Block { 582 583 payload := ClusterPayloadFixture(3) 584 header := BlockHeaderFixture() 585 header.PayloadHash = payload.Hash() 586 587 return cluster.Block{ 588 Header: header, 589 Payload: payload, 590 } 591 } 592 593 func ClusterBlockChainFixture(n int) []cluster.Block { 594 clusterBlocks := make([]cluster.Block, 0, n) 595 596 parent := ClusterBlockFixture() 597 598 for i := 0; i < n; i++ { 599 block := ClusterBlockWithParent(&parent) 600 clusterBlocks = append(clusterBlocks, block) 601 parent = block 602 } 603 604 return clusterBlocks 605 } 606 607 // ClusterBlockWithParent creates a new cluster consensus block that is valid 608 // with respect to the given parent block. 609 func ClusterBlockWithParent(parent *cluster.Block) cluster.Block { 610 611 payload := ClusterPayloadFixture(3) 612 613 header := BlockHeaderFixture() 614 header.Height = parent.Header.Height + 1 615 header.View = parent.Header.View + 1 616 header.ChainID = parent.Header.ChainID 617 header.Timestamp = time.Now() 618 header.ParentID = parent.ID() 619 header.ParentView = parent.Header.View 620 header.PayloadHash = payload.Hash() 621 622 block := cluster.Block{ 623 Header: header, 624 Payload: payload, 625 } 626 627 return block 628 } 629 630 func WithCollRef(refID flow.Identifier) func(*flow.CollectionGuarantee) { 631 return func(guarantee *flow.CollectionGuarantee) { 632 guarantee.ReferenceBlockID = refID 633 } 634 } 635 636 func WithCollection(collection *flow.Collection) func(guarantee *flow.CollectionGuarantee) { 637 return func(guarantee *flow.CollectionGuarantee) { 638 guarantee.CollectionID = collection.ID() 639 } 640 } 641 642 func AddCollectionsToBlock(block *flow.Block, collections []*flow.Collection) { 643 gs := make([]*flow.CollectionGuarantee, 0, len(collections)) 644 for _, collection := range collections { 645 g := collection.Guarantee() 646 gs = append(gs, &g) 647 } 648 649 block.Payload.Guarantees = gs 650 block.SetPayload(*block.Payload) 651 } 652 653 func CollectionGuaranteeFixture(options ...func(*flow.CollectionGuarantee)) *flow.CollectionGuarantee { 654 guarantee := &flow.CollectionGuarantee{ 655 CollectionID: IdentifierFixture(), 656 SignerIndices: RandomBytes(16), 657 Signature: SignatureFixture(), 658 } 659 for _, option := range options { 660 option(guarantee) 661 } 662 return guarantee 663 } 664 665 func CollectionGuaranteesWithCollectionIDFixture(collections []*flow.Collection) []*flow.CollectionGuarantee { 666 guarantees := make([]*flow.CollectionGuarantee, 0, len(collections)) 667 for i := 0; i < len(collections); i++ { 668 guarantee := CollectionGuaranteeFixture(WithCollection(collections[i])) 669 guarantees = append(guarantees, guarantee) 670 } 671 return guarantees 672 } 673 674 func CollectionGuaranteesFixture( 675 n int, 676 options ...func(*flow.CollectionGuarantee), 677 ) []*flow.CollectionGuarantee { 678 guarantees := make([]*flow.CollectionGuarantee, 0, n) 679 for i := 1; i <= n; i++ { 680 guarantee := CollectionGuaranteeFixture(options...) 681 guarantees = append(guarantees, guarantee) 682 } 683 return guarantees 684 } 685 686 func BlockSealsFixture(n int) []*flow.Seal { 687 seals := make([]*flow.Seal, 0, n) 688 for i := 0; i < n; i++ { 689 seal := Seal.Fixture() 690 seals = append(seals, seal) 691 } 692 return seals 693 } 694 695 func CollectionListFixture(n int, options ...func(*flow.Collection)) []*flow.Collection { 696 collections := make([]*flow.Collection, n) 697 for i := 0; i < n; i++ { 698 collection := CollectionFixture(1, options...) 699 collections[i] = &collection 700 } 701 702 return collections 703 } 704 705 func CollectionFixture(n int, options ...func(*flow.Collection)) flow.Collection { 706 transactions := make([]*flow.TransactionBody, 0, n) 707 708 for i := 0; i < n; i++ { 709 tx := TransactionFixture() 710 transactions = append(transactions, &tx.TransactionBody) 711 } 712 713 col := flow.Collection{Transactions: transactions} 714 for _, opt := range options { 715 opt(&col) 716 } 717 return col 718 } 719 720 func FixedReferenceBlockID() flow.Identifier { 721 blockID := flow.Identifier{} 722 blockID[0] = byte(1) 723 return blockID 724 } 725 726 func CompleteCollectionFixture() *entity.CompleteCollection { 727 txBody := TransactionBodyFixture() 728 return &entity.CompleteCollection{ 729 Guarantee: &flow.CollectionGuarantee{ 730 CollectionID: flow.Collection{Transactions: []*flow.TransactionBody{&txBody}}.ID(), 731 Signature: SignatureFixture(), 732 ReferenceBlockID: FixedReferenceBlockID(), 733 SignerIndices: SignerIndicesFixture(1), 734 }, 735 Transactions: []*flow.TransactionBody{&txBody}, 736 } 737 } 738 739 func CompleteCollectionFromTransactions(txs []*flow.TransactionBody) *entity.CompleteCollection { 740 return &entity.CompleteCollection{ 741 Guarantee: &flow.CollectionGuarantee{ 742 CollectionID: flow.Collection{Transactions: txs}.ID(), 743 Signature: SignatureFixture(), 744 ReferenceBlockID: IdentifierFixture(), 745 SignerIndices: SignerIndicesFixture(3), 746 }, 747 Transactions: txs, 748 } 749 } 750 751 func ExecutableBlockFixture( 752 collectionsSignerIDs [][]flow.Identifier, 753 startState *flow.StateCommitment, 754 ) *entity.ExecutableBlock { 755 756 header := BlockHeaderFixture() 757 return ExecutableBlockFixtureWithParent(collectionsSignerIDs, header, startState) 758 } 759 760 func ExecutableBlockFixtureWithParent( 761 collectionsSignerIDs [][]flow.Identifier, 762 parent *flow.Header, 763 startState *flow.StateCommitment, 764 ) *entity.ExecutableBlock { 765 766 completeCollections := make(map[flow.Identifier]*entity.CompleteCollection, len(collectionsSignerIDs)) 767 block := BlockWithParentFixture(parent) 768 block.Payload.Guarantees = nil 769 770 for range collectionsSignerIDs { 771 completeCollection := CompleteCollectionFixture() 772 block.Payload.Guarantees = append(block.Payload.Guarantees, completeCollection.Guarantee) 773 completeCollections[completeCollection.Guarantee.CollectionID] = completeCollection 774 } 775 776 block.Header.PayloadHash = block.Payload.Hash() 777 778 executableBlock := &entity.ExecutableBlock{ 779 Block: block, 780 CompleteCollections: completeCollections, 781 StartState: startState, 782 } 783 return executableBlock 784 } 785 786 func ExecutableBlockFromTransactions( 787 chain flow.ChainID, 788 txss [][]*flow.TransactionBody, 789 ) *entity.ExecutableBlock { 790 791 completeCollections := make(map[flow.Identifier]*entity.CompleteCollection, len(txss)) 792 blockHeader := BlockHeaderFixtureOnChain(chain) 793 block := *BlockWithParentFixture(blockHeader) 794 block.Payload.Guarantees = nil 795 796 for _, txs := range txss { 797 cc := CompleteCollectionFromTransactions(txs) 798 block.Payload.Guarantees = append(block.Payload.Guarantees, cc.Guarantee) 799 completeCollections[cc.Guarantee.CollectionID] = cc 800 } 801 802 block.Header.PayloadHash = block.Payload.Hash() 803 804 executableBlock := &entity.ExecutableBlock{ 805 Block: &block, 806 CompleteCollections: completeCollections, 807 } 808 // Preload the id 809 executableBlock.ID() 810 return executableBlock 811 } 812 813 func WithExecutorID(executorID flow.Identifier) func(*flow.ExecutionReceipt) { 814 return func(er *flow.ExecutionReceipt) { 815 er.ExecutorID = executorID 816 } 817 } 818 819 func WithResult(result *flow.ExecutionResult) func(*flow.ExecutionReceipt) { 820 return func(receipt *flow.ExecutionReceipt) { 821 receipt.ExecutionResult = *result 822 } 823 } 824 825 func WithSpocks(spocks []crypto.Signature) func(*flow.ExecutionReceipt) { 826 return func(receipt *flow.ExecutionReceipt) { 827 receipt.Spocks = spocks 828 } 829 } 830 831 func ExecutionReceiptFixture(opts ...func(*flow.ExecutionReceipt)) *flow.ExecutionReceipt { 832 receipt := &flow.ExecutionReceipt{ 833 ExecutorID: IdentifierFixture(), 834 ExecutionResult: *ExecutionResultFixture(), 835 Spocks: nil, 836 ExecutorSignature: SignatureFixture(), 837 } 838 839 for _, apply := range opts { 840 apply(receipt) 841 } 842 843 return receipt 844 } 845 846 func ReceiptForBlockFixture(block *flow.Block) *flow.ExecutionReceipt { 847 return ReceiptForBlockExecutorFixture(block, IdentifierFixture()) 848 } 849 850 func ReceiptForBlockExecutorFixture( 851 block *flow.Block, 852 executor flow.Identifier, 853 ) *flow.ExecutionReceipt { 854 result := ExecutionResultFixture(WithBlock(block)) 855 receipt := ExecutionReceiptFixture(WithResult(result), WithExecutorID(executor)) 856 return receipt 857 } 858 859 func ReceiptsForBlockFixture( 860 block *flow.Block, 861 ids []flow.Identifier, 862 ) []*flow.ExecutionReceipt { 863 result := ExecutionResultFixture(WithBlock(block)) 864 var ers []*flow.ExecutionReceipt 865 for _, id := range ids { 866 ers = append(ers, ExecutionReceiptFixture(WithResult(result), WithExecutorID(id))) 867 } 868 return ers 869 } 870 871 func WithPreviousResult(prevResult flow.ExecutionResult) func(*flow.ExecutionResult) { 872 return func(result *flow.ExecutionResult) { 873 result.PreviousResultID = prevResult.ID() 874 finalState, err := prevResult.FinalStateCommitment() 875 if err != nil { 876 panic("missing final state commitment") 877 } 878 result.Chunks[0].StartState = finalState 879 } 880 } 881 882 func WithBlock(block *flow.Block) func(*flow.ExecutionResult) { 883 chunks := 1 // tailing chunk is always system chunk 884 var previousResultID flow.Identifier 885 if block.Payload != nil { 886 chunks += len(block.Payload.Guarantees) 887 } 888 blockID := block.ID() 889 890 return func(result *flow.ExecutionResult) { 891 startState := result.Chunks[0].StartState // retain previous start state in case it was user-defined 892 result.BlockID = blockID 893 result.Chunks = ChunkListFixture(uint(chunks), blockID) 894 result.Chunks[0].StartState = startState // set start state to value before update 895 result.PreviousResultID = previousResultID 896 } 897 } 898 899 func WithChunks(n uint) func(*flow.ExecutionResult) { 900 return func(result *flow.ExecutionResult) { 901 result.Chunks = ChunkListFixture(n, result.BlockID) 902 } 903 } 904 905 func ExecutionResultListFixture( 906 n int, 907 opts ...func(*flow.ExecutionResult), 908 ) []*flow.ExecutionResult { 909 results := make([]*flow.ExecutionResult, 0, n) 910 for i := 0; i < n; i++ { 911 results = append(results, ExecutionResultFixture(opts...)) 912 } 913 914 return results 915 } 916 917 func WithExecutionResultBlockID(blockID flow.Identifier) func(*flow.ExecutionResult) { 918 return func(result *flow.ExecutionResult) { 919 result.BlockID = blockID 920 for _, chunk := range result.Chunks { 921 chunk.BlockID = blockID 922 } 923 } 924 } 925 926 func WithFinalState(commit flow.StateCommitment) func(*flow.ExecutionResult) { 927 return func(result *flow.ExecutionResult) { 928 result.Chunks[len(result.Chunks)-1].EndState = commit 929 } 930 } 931 932 func WithServiceEvents(n int) func(result *flow.ExecutionResult) { 933 return func(result *flow.ExecutionResult) { 934 result.ServiceEvents = ServiceEventsFixture(n) 935 } 936 } 937 938 func WithExecutionDataID(id flow.Identifier) func(result *flow.ExecutionResult) { 939 return func(result *flow.ExecutionResult) { 940 result.ExecutionDataID = id 941 } 942 } 943 944 func ServiceEventsFixture(n int) flow.ServiceEventList { 945 sel := make(flow.ServiceEventList, n) 946 947 for i := 0; i < n; i++ { 948 switch i % 3 { 949 case 0: 950 sel[i] = EpochCommitFixture().ServiceEvent() 951 case 1: 952 sel[i] = EpochSetupFixture().ServiceEvent() 953 case 2: 954 sel[i] = VersionBeaconFixture().ServiceEvent() 955 } 956 } 957 958 return sel 959 } 960 961 func ExecutionResultFixture(opts ...func(*flow.ExecutionResult)) *flow.ExecutionResult { 962 blockID := IdentifierFixture() 963 result := &flow.ExecutionResult{ 964 PreviousResultID: IdentifierFixture(), 965 BlockID: IdentifierFixture(), 966 Chunks: ChunkListFixture(2, blockID), 967 ExecutionDataID: IdentifierFixture(), 968 } 969 970 for _, apply := range opts { 971 apply(result) 972 } 973 974 return result 975 } 976 977 func WithApproverID(approverID flow.Identifier) func(*flow.ResultApproval) { 978 return func(ra *flow.ResultApproval) { 979 ra.Body.ApproverID = approverID 980 } 981 } 982 983 func WithAttestationBlock(block *flow.Block) func(*flow.ResultApproval) { 984 return func(ra *flow.ResultApproval) { 985 ra.Body.Attestation.BlockID = block.ID() 986 } 987 } 988 989 func WithExecutionResultID(id flow.Identifier) func(*flow.ResultApproval) { 990 return func(ra *flow.ResultApproval) { 991 ra.Body.ExecutionResultID = id 992 } 993 } 994 995 func WithBlockID(id flow.Identifier) func(*flow.ResultApproval) { 996 return func(ra *flow.ResultApproval) { 997 ra.Body.BlockID = id 998 } 999 } 1000 1001 func WithChunk(chunkIdx uint64) func(*flow.ResultApproval) { 1002 return func(approval *flow.ResultApproval) { 1003 approval.Body.ChunkIndex = chunkIdx 1004 } 1005 } 1006 1007 func ResultApprovalFixture(opts ...func(*flow.ResultApproval)) *flow.ResultApproval { 1008 attestation := flow.Attestation{ 1009 BlockID: IdentifierFixture(), 1010 ExecutionResultID: IdentifierFixture(), 1011 ChunkIndex: uint64(0), 1012 } 1013 1014 approval := flow.ResultApproval{ 1015 Body: flow.ResultApprovalBody{ 1016 Attestation: attestation, 1017 ApproverID: IdentifierFixture(), 1018 AttestationSignature: SignatureFixture(), 1019 Spock: nil, 1020 }, 1021 VerifierSignature: SignatureFixture(), 1022 } 1023 1024 for _, apply := range opts { 1025 apply(&approval) 1026 } 1027 1028 return &approval 1029 } 1030 1031 func AttestationFixture() *flow.Attestation { 1032 return &flow.Attestation{ 1033 BlockID: IdentifierFixture(), 1034 ExecutionResultID: IdentifierFixture(), 1035 ChunkIndex: uint64(0), 1036 } 1037 } 1038 1039 func StateCommitmentFixture() flow.StateCommitment { 1040 var state flow.StateCommitment 1041 _, _ = crand.Read(state[:]) 1042 return state 1043 } 1044 1045 func StateCommitmentPointerFixture() *flow.StateCommitment { 1046 state := StateCommitmentFixture() 1047 return &state 1048 } 1049 1050 func HashFixture(size int) hash.Hash { 1051 hash := make(hash.Hash, size) 1052 for i := 0; i < size; i++ { 1053 hash[i] = byte(i) 1054 } 1055 return hash 1056 } 1057 1058 func IdentifierListFixture(n int) flow.IdentifierList { 1059 list := make([]flow.Identifier, n) 1060 for i := 0; i < n; i++ { 1061 list[i] = IdentifierFixture() 1062 } 1063 return list 1064 } 1065 1066 func IdentifierFixture() flow.Identifier { 1067 var id flow.Identifier 1068 _, _ = crand.Read(id[:]) 1069 return id 1070 } 1071 1072 func SignerIndicesFixture(n int) []byte { 1073 indices := bitutils.MakeBitVector(10) 1074 for i := 0; i < n; i++ { 1075 bitutils.SetBit(indices, 1) 1076 } 1077 return indices 1078 } 1079 1080 func SignerIndicesByIndices(n int, indices []int) []byte { 1081 signers := bitutils.MakeBitVector(n) 1082 for _, i := range indices { 1083 bitutils.SetBit(signers, i) 1084 } 1085 return signers 1086 } 1087 1088 // WithRole adds a role to an identity fixture. 1089 func WithRole(role flow.Role) func(*flow.Identity) { 1090 return func(identity *flow.Identity) { 1091 identity.Role = role 1092 } 1093 } 1094 1095 // WithInitialWeight sets the initial weight on an identity fixture. 1096 func WithInitialWeight(weight uint64) func(*flow.Identity) { 1097 return func(identity *flow.Identity) { 1098 identity.InitialWeight = weight 1099 } 1100 } 1101 1102 // WithParticipationStatus sets the epoch participation status on an identity fixture. 1103 func WithParticipationStatus(status flow.EpochParticipationStatus) func(*flow.Identity) { 1104 return func(identity *flow.Identity) { 1105 identity.EpochParticipationStatus = status 1106 } 1107 } 1108 1109 // WithAddress sets the network address of identity fixture. 1110 func WithAddress(address string) func(*flow.Identity) { 1111 return func(identity *flow.Identity) { 1112 identity.Address = address 1113 } 1114 } 1115 1116 // WithNetworkingKey sets the networking public key of identity fixture. 1117 func WithNetworkingKey(key crypto.PublicKey) func(*flow.Identity) { 1118 return func(identity *flow.Identity) { 1119 identity.NetworkPubKey = key 1120 } 1121 } 1122 1123 func RandomBytes(n int) []byte { 1124 b := make([]byte, n) 1125 read, err := crand.Read(b) 1126 if err != nil { 1127 panic("cannot read random bytes") 1128 } 1129 if read != n { 1130 panic(fmt.Errorf("cannot read enough random bytes (got %d of %d)", read, n)) 1131 } 1132 return b 1133 } 1134 1135 func NodeConfigFixture(opts ...func(*flow.Identity)) bootstrap.NodeConfig { 1136 identity := IdentityFixture(opts...) 1137 return bootstrap.NodeConfig{ 1138 Role: identity.Role, 1139 Address: identity.Address, 1140 Weight: identity.InitialWeight, 1141 } 1142 } 1143 1144 func NodeInfoFixture(opts ...func(*flow.Identity)) bootstrap.NodeInfo { 1145 opts = append(opts, WithKeys) 1146 return bootstrap.NodeInfoFromIdentity(IdentityFixture(opts...)) 1147 } 1148 1149 func NodeInfosFixture(n int, opts ...func(*flow.Identity)) []bootstrap.NodeInfo { 1150 opts = append(opts, WithKeys) 1151 il := IdentityListFixture(n, opts...) 1152 nodeInfos := make([]bootstrap.NodeInfo, 0, n) 1153 for _, identity := range il { 1154 nodeInfos = append(nodeInfos, bootstrap.NodeInfoFromIdentity(identity)) 1155 } 1156 return nodeInfos 1157 } 1158 1159 func PrivateNodeInfoFixture(opts ...func(*flow.Identity)) bootstrap.NodeInfo { 1160 return PrivateNodeInfosFixture(1, opts...)[0] 1161 } 1162 1163 func PrivateNodeInfosFixture(n int, opts ...func(*flow.Identity)) []bootstrap.NodeInfo { 1164 return PrivateNodeInfosFromIdentityList(IdentityListFixture(n, opts...)) 1165 } 1166 1167 func PrivateNodeInfosFromIdentityList(il flow.IdentityList) []bootstrap.NodeInfo { 1168 nodeInfos := make([]bootstrap.NodeInfo, 0, len(il)) 1169 for _, identity := range il { 1170 nodeInfo := bootstrap.PrivateNodeInfoFromIdentity(identity, KeyFixture(crypto.ECDSAP256), KeyFixture(crypto.BLSBLS12381)) 1171 nodeInfos = append(nodeInfos, nodeInfo) 1172 } 1173 return nodeInfos 1174 } 1175 1176 // IdentityFixture returns a node identity. 1177 func IdentityFixture(opts ...func(*flow.Identity)) *flow.Identity { 1178 nodeID := IdentifierFixture() 1179 stakingKey := StakingPrivKeyByIdentifier(nodeID) 1180 identity := flow.Identity{ 1181 IdentitySkeleton: flow.IdentitySkeleton{ 1182 NodeID: nodeID, 1183 Address: fmt.Sprintf("address-%x", nodeID[0:7]), 1184 Role: flow.RoleConsensus, 1185 InitialWeight: 1000, 1186 StakingPubKey: stakingKey.PublicKey(), 1187 }, 1188 DynamicIdentity: flow.DynamicIdentity{ 1189 EpochParticipationStatus: flow.EpochParticipationStatusActive, 1190 }, 1191 } 1192 for _, apply := range opts { 1193 apply(&identity) 1194 } 1195 return &identity 1196 } 1197 1198 // IdentityWithNetworkingKeyFixture returns a node identity and networking private key 1199 func IdentityWithNetworkingKeyFixture(opts ...func(*flow.Identity)) ( 1200 *flow.Identity, 1201 crypto.PrivateKey, 1202 ) { 1203 networkKey := NetworkingPrivKeyFixture() 1204 opts = append(opts, WithNetworkingKey(networkKey.PublicKey())) 1205 id := IdentityFixture(opts...) 1206 return id, networkKey 1207 } 1208 1209 func WithKeys(identity *flow.Identity) { 1210 staking := StakingPrivKeyFixture() 1211 networking := NetworkingPrivKeyFixture() 1212 identity.StakingPubKey = staking.PublicKey() 1213 identity.NetworkPubKey = networking.PublicKey() 1214 } 1215 1216 // WithNodeID adds a node ID with the given first byte to an identity. 1217 func WithNodeID(id flow.Identifier) func(*flow.Identity) { 1218 return func(identity *flow.Identity) { 1219 identity.NodeID = id 1220 } 1221 } 1222 1223 // WithStakingPubKey adds a staking public key to the identity 1224 func WithStakingPubKey(pubKey crypto.PublicKey) func(*flow.Identity) { 1225 return func(identity *flow.Identity) { 1226 identity.StakingPubKey = pubKey 1227 } 1228 } 1229 1230 // WithRandomPublicKeys adds random public keys to an identity. 1231 func WithRandomPublicKeys() func(*flow.Identity) { 1232 return func(identity *flow.Identity) { 1233 identity.StakingPubKey = KeyFixture(crypto.BLSBLS12381).PublicKey() 1234 identity.NetworkPubKey = KeyFixture(crypto.ECDSAP256).PublicKey() 1235 } 1236 } 1237 1238 // WithAllRoles can be used used to ensure an IdentityList fixtures contains 1239 // all the roles required for a valid genesis block. 1240 func WithAllRoles() func(*flow.Identity) { 1241 return WithAllRolesExcept() 1242 } 1243 1244 // Same as above, but omitting a certain role for cases where we are manually 1245 // setting up nodes or a particular role. 1246 func WithAllRolesExcept(except ...flow.Role) func(*flow.Identity) { 1247 i := 0 1248 roles := flow.Roles() 1249 1250 // remove omitted roles 1251 for _, omitRole := range except { 1252 for i, role := range roles { 1253 if role == omitRole { 1254 roles = append(roles[:i], roles[i+1:]...) 1255 } 1256 } 1257 } 1258 1259 return func(id *flow.Identity) { 1260 id.Role = roles[i%len(roles)] 1261 i++ 1262 } 1263 } 1264 1265 // CompleteIdentitySet takes a number of identities and completes the missing roles. 1266 func CompleteIdentitySet(identities ...*flow.Identity) flow.IdentityList { 1267 required := map[flow.Role]struct{}{ 1268 flow.RoleCollection: {}, 1269 flow.RoleConsensus: {}, 1270 flow.RoleExecution: {}, 1271 flow.RoleVerification: {}, 1272 } 1273 // don't add identities for roles that already exist 1274 for _, identity := range identities { 1275 delete(required, identity.Role) 1276 } 1277 // add identities for missing roles 1278 for role := range required { 1279 identities = append(identities, IdentityFixture(WithRole(role))) 1280 } 1281 return identities 1282 } 1283 1284 // IdentityListFixture returns a list of node identity objects. The identities 1285 // can be customized (ie. set their role) by passing in a function that modifies 1286 // the input identities as required. 1287 func IdentityListFixture(n int, opts ...func(*flow.Identity)) flow.IdentityList { 1288 identities := make(flow.IdentityList, 0, n) 1289 1290 for i := 0; i < n; i++ { 1291 identity := IdentityFixture() 1292 identity.Address = fmt.Sprintf("%x@flow.com:1234", identity.NodeID) 1293 for _, opt := range opts { 1294 opt(identity) 1295 } 1296 identities = append(identities, identity) 1297 } 1298 1299 return identities 1300 } 1301 1302 func WithChunkStartState(startState flow.StateCommitment) func(chunk *flow.Chunk) { 1303 return func(chunk *flow.Chunk) { 1304 chunk.StartState = startState 1305 } 1306 } 1307 1308 func ChunkFixture( 1309 blockID flow.Identifier, 1310 collectionIndex uint, 1311 opts ...func(*flow.Chunk), 1312 ) *flow.Chunk { 1313 chunk := &flow.Chunk{ 1314 ChunkBody: flow.ChunkBody{ 1315 CollectionIndex: collectionIndex, 1316 StartState: StateCommitmentFixture(), 1317 EventCollection: IdentifierFixture(), 1318 TotalComputationUsed: 4200, 1319 NumberOfTransactions: 42, 1320 BlockID: blockID, 1321 }, 1322 Index: 0, 1323 EndState: StateCommitmentFixture(), 1324 } 1325 1326 for _, opt := range opts { 1327 opt(chunk) 1328 } 1329 1330 return chunk 1331 } 1332 1333 func ChunkListFixture(n uint, blockID flow.Identifier) flow.ChunkList { 1334 chunks := make([]*flow.Chunk, 0, n) 1335 for i := uint64(0); i < uint64(n); i++ { 1336 chunk := ChunkFixture(blockID, uint(i)) 1337 chunk.Index = i 1338 chunks = append(chunks, chunk) 1339 } 1340 return chunks 1341 } 1342 1343 func ChunkLocatorListFixture(n uint) chunks.LocatorList { 1344 locators := chunks.LocatorList{} 1345 resultID := IdentifierFixture() 1346 for i := uint64(0); i < uint64(n); i++ { 1347 locator := ChunkLocatorFixture(resultID, i) 1348 locators = append(locators, locator) 1349 } 1350 return locators 1351 } 1352 1353 func ChunkLocatorFixture(resultID flow.Identifier, index uint64) *chunks.Locator { 1354 return &chunks.Locator{ 1355 ResultID: resultID, 1356 Index: index, 1357 } 1358 } 1359 1360 // ChunkStatusListToChunkLocatorFixture extracts chunk locators from a list of chunk statuses. 1361 func ChunkStatusListToChunkLocatorFixture(statuses []*verification.ChunkStatus) chunks.LocatorMap { 1362 locators := chunks.LocatorMap{} 1363 for _, status := range statuses { 1364 locator := ChunkLocatorFixture(status.ExecutionResult.ID(), status.ChunkIndex) 1365 locators[locator.ID()] = locator 1366 } 1367 1368 return locators 1369 } 1370 1371 // ChunkStatusListFixture receives an execution result, samples `n` chunks out of it and 1372 // creates a chunk status for them. 1373 // It returns the list of sampled chunk statuses for the result. 1374 func ChunkStatusListFixture( 1375 t *testing.T, 1376 blockHeight uint64, 1377 result *flow.ExecutionResult, 1378 n int, 1379 ) verification.ChunkStatusList { 1380 statuses := verification.ChunkStatusList{} 1381 1382 // result should have enough chunk to sample 1383 require.GreaterOrEqual(t, len(result.Chunks), n) 1384 1385 chunkList := make(flow.ChunkList, n) 1386 copy(chunkList, result.Chunks) 1387 rand.Shuffle(len(chunkList), func(i, j int) { chunkList[i], chunkList[j] = chunkList[j], chunkList[i] }) 1388 1389 for _, chunk := range chunkList[:n] { 1390 status := &verification.ChunkStatus{ 1391 ChunkIndex: chunk.Index, 1392 BlockHeight: blockHeight, 1393 ExecutionResult: result, 1394 } 1395 statuses = append(statuses, status) 1396 } 1397 1398 return statuses 1399 } 1400 1401 func qcSignatureDataFixture() hotstuff.SignatureData { 1402 sigType := RandomBytes(5) 1403 for i := range sigType { 1404 sigType[i] = sigType[i] % 2 1405 } 1406 sigData := hotstuff.SignatureData{ 1407 SigType: sigType, 1408 AggregatedStakingSig: SignatureFixture(), 1409 AggregatedRandomBeaconSig: SignatureFixture(), 1410 ReconstructedRandomBeaconSig: SignatureFixture(), 1411 } 1412 return sigData 1413 } 1414 1415 func QCSigDataFixture() []byte { 1416 packer := hotstuff.SigDataPacker{} 1417 sigData := qcSignatureDataFixture() 1418 encoded, _ := packer.Encode(&sigData) 1419 return encoded 1420 } 1421 1422 func QCSigDataWithSoRFixture(sor []byte) []byte { 1423 packer := hotstuff.SigDataPacker{} 1424 sigData := qcSignatureDataFixture() 1425 sigData.ReconstructedRandomBeaconSig = sor 1426 encoded, _ := packer.Encode(&sigData) 1427 return encoded 1428 } 1429 1430 func SignatureFixture() crypto.Signature { 1431 sig := make([]byte, crypto.SignatureLenBLSBLS12381) 1432 _, _ = crand.Read(sig) 1433 return sig 1434 } 1435 1436 func SignaturesFixture(n int) []crypto.Signature { 1437 var sigs []crypto.Signature 1438 for i := 0; i < n; i++ { 1439 sigs = append(sigs, SignatureFixture()) 1440 } 1441 return sigs 1442 } 1443 1444 func RandomSourcesFixture(n int) [][]byte { 1445 var sigs [][]byte 1446 for i := 0; i < n; i++ { 1447 sigs = append(sigs, SignatureFixture()) 1448 } 1449 return sigs 1450 } 1451 1452 func TransactionFixture(n ...func(t *flow.Transaction)) flow.Transaction { 1453 tx := flow.Transaction{TransactionBody: TransactionBodyFixture()} 1454 if len(n) > 0 { 1455 n[0](&tx) 1456 } 1457 return tx 1458 } 1459 1460 func TransactionBodyFixture(opts ...func(*flow.TransactionBody)) flow.TransactionBody { 1461 tb := flow.TransactionBody{ 1462 Script: []byte("access(all) fun main() {}"), 1463 ReferenceBlockID: IdentifierFixture(), 1464 GasLimit: 10, 1465 ProposalKey: ProposalKeyFixture(), 1466 Payer: AddressFixture(), 1467 Authorizers: []flow.Address{AddressFixture()}, 1468 EnvelopeSignatures: []flow.TransactionSignature{TransactionSignatureFixture()}, 1469 } 1470 1471 for _, apply := range opts { 1472 apply(&tb) 1473 } 1474 1475 return tb 1476 } 1477 1478 func TransactionBodyListFixture(n int) []flow.TransactionBody { 1479 l := make([]flow.TransactionBody, n) 1480 for i := 0; i < n; i++ { 1481 l[i] = TransactionBodyFixture() 1482 } 1483 1484 return l 1485 } 1486 1487 func WithTransactionDSL(txDSL dsl.Transaction) func(tx *flow.TransactionBody) { 1488 return func(tx *flow.TransactionBody) { 1489 tx.Script = []byte(txDSL.ToCadence()) 1490 } 1491 } 1492 1493 func WithReferenceBlock(id flow.Identifier) func(tx *flow.TransactionBody) { 1494 return func(tx *flow.TransactionBody) { 1495 tx.ReferenceBlockID = id 1496 } 1497 } 1498 1499 func TransactionDSLFixture(chain flow.Chain) dsl.Transaction { 1500 return dsl.Transaction{ 1501 Import: dsl.Import{Address: sdk.Address(chain.ServiceAddress())}, 1502 Content: dsl.Prepare{ 1503 Content: dsl.Code(` 1504 access(all) fun main() {} 1505 `), 1506 }, 1507 } 1508 } 1509 1510 // RegisterIDFixture returns a RegisterID with a fixed key and owner 1511 func RegisterIDFixture() flow.RegisterID { 1512 return flow.NewRegisterID(RandomAddressFixture(), "key") 1513 } 1514 1515 // VerifiableChunkDataFixture returns a complete verifiable chunk with an 1516 // execution receipt referencing the block/collections. 1517 func VerifiableChunkDataFixture(chunkIndex uint64) *verification.VerifiableChunkData { 1518 1519 guarantees := make([]*flow.CollectionGuarantee, 0) 1520 1521 var col flow.Collection 1522 1523 for i := 0; i <= int(chunkIndex); i++ { 1524 col = CollectionFixture(1) 1525 guarantee := col.Guarantee() 1526 guarantees = append(guarantees, &guarantee) 1527 } 1528 1529 payload := flow.Payload{ 1530 Guarantees: guarantees, 1531 Seals: nil, 1532 } 1533 header := BlockHeaderFixture() 1534 header.PayloadHash = payload.Hash() 1535 1536 block := flow.Block{ 1537 Header: header, 1538 Payload: &payload, 1539 } 1540 1541 chunks := make([]*flow.Chunk, 0) 1542 1543 var chunk flow.Chunk 1544 1545 for i := 0; i <= int(chunkIndex); i++ { 1546 chunk = flow.Chunk{ 1547 ChunkBody: flow.ChunkBody{ 1548 CollectionIndex: uint(i), 1549 StartState: StateCommitmentFixture(), 1550 BlockID: block.ID(), 1551 }, 1552 Index: uint64(i), 1553 } 1554 chunks = append(chunks, &chunk) 1555 } 1556 1557 result := flow.ExecutionResult{ 1558 BlockID: block.ID(), 1559 Chunks: chunks, 1560 } 1561 1562 // computes chunk end state 1563 index := chunk.Index 1564 var endState flow.StateCommitment 1565 if int(index) == len(result.Chunks)-1 { 1566 // last chunk in receipt takes final state commitment 1567 endState = StateCommitmentFixture() 1568 } else { 1569 // any chunk except last takes the subsequent chunk's start state 1570 endState = result.Chunks[index+1].StartState 1571 } 1572 1573 return &verification.VerifiableChunkData{ 1574 Chunk: &chunk, 1575 Header: block.Header, 1576 Result: &result, 1577 ChunkDataPack: ChunkDataPackFixture(result.ID()), 1578 EndState: endState, 1579 } 1580 } 1581 1582 // ChunkDataResponseMsgFixture creates a chunk data response message with a single-transaction collection, and random chunk ID. 1583 // Use options to customize the response. 1584 func ChunkDataResponseMsgFixture( 1585 chunkID flow.Identifier, 1586 opts ...func(*messages.ChunkDataResponse), 1587 ) *messages.ChunkDataResponse { 1588 cdp := &messages.ChunkDataResponse{ 1589 ChunkDataPack: *ChunkDataPackFixture(chunkID), 1590 Nonce: rand.Uint64(), 1591 } 1592 1593 for _, opt := range opts { 1594 opt(cdp) 1595 } 1596 1597 return cdp 1598 } 1599 1600 // WithApproximateSize sets the ChunkDataResponse to be approximately bytes in size. 1601 func WithApproximateSize(bytes uint64) func(*messages.ChunkDataResponse) { 1602 return func(request *messages.ChunkDataResponse) { 1603 // 1 tx fixture is approximately 350 bytes 1604 txCount := bytes / 350 1605 collection := CollectionFixture(int(txCount) + 1) 1606 pack := ChunkDataPackFixture(request.ChunkDataPack.ChunkID, WithChunkDataPackCollection(&collection)) 1607 request.ChunkDataPack = *pack 1608 } 1609 } 1610 1611 // ChunkDataResponseMessageListFixture creates a list of chunk data response messages each with a single-transaction collection, and random chunk ID. 1612 func ChunkDataResponseMessageListFixture(chunkIDs flow.IdentifierList) []*messages.ChunkDataResponse { 1613 lst := make([]*messages.ChunkDataResponse, 0, len(chunkIDs)) 1614 for _, chunkID := range chunkIDs { 1615 lst = append(lst, ChunkDataResponseMsgFixture(chunkID)) 1616 } 1617 return lst 1618 } 1619 1620 // ChunkDataPackRequestListFixture creates and returns a list of chunk data pack requests fixtures. 1621 func ChunkDataPackRequestListFixture( 1622 n int, 1623 opts ...func(*verification.ChunkDataPackRequest), 1624 ) verification.ChunkDataPackRequestList { 1625 lst := make([]*verification.ChunkDataPackRequest, 0, n) 1626 for i := 0; i < n; i++ { 1627 lst = append(lst, ChunkDataPackRequestFixture(opts...)) 1628 } 1629 return lst 1630 } 1631 1632 func WithHeight(height uint64) func(*verification.ChunkDataPackRequest) { 1633 return func(request *verification.ChunkDataPackRequest) { 1634 request.Height = height 1635 } 1636 } 1637 1638 func WithHeightGreaterThan(height uint64) func(*verification.ChunkDataPackRequest) { 1639 return func(request *verification.ChunkDataPackRequest) { 1640 request.Height = height + 1 1641 } 1642 } 1643 1644 func WithAgrees(list flow.IdentifierList) func(*verification.ChunkDataPackRequest) { 1645 return func(request *verification.ChunkDataPackRequest) { 1646 request.Agrees = list 1647 } 1648 } 1649 1650 func WithDisagrees(list flow.IdentifierList) func(*verification.ChunkDataPackRequest) { 1651 return func(request *verification.ChunkDataPackRequest) { 1652 request.Disagrees = list 1653 } 1654 } 1655 1656 func WithChunkID(chunkID flow.Identifier) func(*verification.ChunkDataPackRequest) { 1657 return func(request *verification.ChunkDataPackRequest) { 1658 request.ChunkID = chunkID 1659 } 1660 } 1661 1662 // ChunkDataPackRequestFixture creates a chunk data request with some default values, i.e., one agree execution node, one disagree execution node, 1663 // and height of zero. 1664 // Use options to customize the request. 1665 func ChunkDataPackRequestFixture(opts ...func(*verification.ChunkDataPackRequest)) *verification. 1666 ChunkDataPackRequest { 1667 1668 req := &verification.ChunkDataPackRequest{ 1669 Locator: chunks.Locator{ 1670 ResultID: IdentifierFixture(), 1671 Index: 0, 1672 }, 1673 ChunkDataPackRequestInfo: verification.ChunkDataPackRequestInfo{ 1674 ChunkID: IdentifierFixture(), 1675 Height: 0, 1676 Agrees: IdentifierListFixture(1), 1677 Disagrees: IdentifierListFixture(1), 1678 }, 1679 } 1680 1681 for _, opt := range opts { 1682 opt(req) 1683 } 1684 1685 // creates identity fixtures for target ids as union of agrees and disagrees 1686 // TODO: remove this inner fixture once we have filter for identifier list. 1687 targets := flow.IdentityList{} 1688 for _, id := range req.Agrees { 1689 targets = append(targets, IdentityFixture(WithNodeID(id), WithRole(flow.RoleExecution))) 1690 } 1691 for _, id := range req.Disagrees { 1692 targets = append(targets, IdentityFixture(WithNodeID(id), WithRole(flow.RoleExecution))) 1693 } 1694 1695 req.Targets = targets 1696 1697 return req 1698 } 1699 1700 func WithChunkDataPackCollection(collection *flow.Collection) func(*flow.ChunkDataPack) { 1701 return func(cdp *flow.ChunkDataPack) { 1702 cdp.Collection = collection 1703 } 1704 } 1705 1706 func WithStartState(startState flow.StateCommitment) func(*flow.ChunkDataPack) { 1707 return func(cdp *flow.ChunkDataPack) { 1708 cdp.StartState = startState 1709 } 1710 } 1711 1712 func ChunkDataPackFixture( 1713 chunkID flow.Identifier, 1714 opts ...func(*flow.ChunkDataPack), 1715 ) *flow.ChunkDataPack { 1716 coll := CollectionFixture(1) 1717 cdp := &flow.ChunkDataPack{ 1718 ChunkID: chunkID, 1719 StartState: StateCommitmentFixture(), 1720 Proof: []byte{'p'}, 1721 Collection: &coll, 1722 ExecutionDataRoot: flow.BlockExecutionDataRoot{ 1723 BlockID: IdentifierFixture(), 1724 ChunkExecutionDataIDs: []cid.Cid{flow.IdToCid(IdentifierFixture())}, 1725 }, 1726 } 1727 1728 for _, opt := range opts { 1729 opt(cdp) 1730 } 1731 1732 return cdp 1733 } 1734 1735 func ChunkDataPacksFixture( 1736 count int, 1737 opts ...func(*flow.ChunkDataPack), 1738 ) []*flow.ChunkDataPack { 1739 chunkDataPacks := make([]*flow.ChunkDataPack, count) 1740 for i := 0; i < count; i++ { 1741 chunkDataPacks[i] = ChunkDataPackFixture(IdentifierFixture()) 1742 } 1743 1744 return chunkDataPacks 1745 } 1746 1747 // SeedFixture returns a random []byte with length n 1748 func SeedFixture(n int) []byte { 1749 var seed = make([]byte, n) 1750 _, _ = crand.Read(seed) 1751 return seed 1752 } 1753 1754 // SeedFixtures returns a list of m random []byte, each having length n 1755 func SeedFixtures(m int, n int) [][]byte { 1756 var seeds = make([][]byte, m, n) 1757 for i := range seeds { 1758 seeds[i] = SeedFixture(n) 1759 } 1760 return seeds 1761 } 1762 1763 // BlockEventsFixture returns a block events model populated with random events of length n. 1764 func BlockEventsFixture( 1765 header *flow.Header, 1766 n int, 1767 types ...flow.EventType, 1768 ) flow.BlockEvents { 1769 return flow.BlockEvents{ 1770 BlockID: header.ID(), 1771 BlockHeight: header.Height, 1772 BlockTimestamp: header.Timestamp, 1773 Events: EventsFixture(n, types...), 1774 } 1775 } 1776 1777 func EventsFixture( 1778 n int, 1779 types ...flow.EventType, 1780 ) []flow.Event { 1781 if len(types) == 0 { 1782 types = []flow.EventType{"A.0x1.Foo.Bar", "A.0x2.Zoo.Moo", "A.0x3.Goo.Hoo"} 1783 } 1784 1785 events := make([]flow.Event, n) 1786 for i := 0; i < n; i++ { 1787 events[i] = EventFixture(types[i%len(types)], 0, uint32(i), IdentifierFixture(), 0) 1788 } 1789 1790 return events 1791 } 1792 1793 func EventTypeFixture(chainID flow.ChainID) flow.EventType { 1794 eventType := fmt.Sprintf("A.%s.TestContract.TestEvent1", RandomAddressFixtureForChain(chainID)) 1795 return flow.EventType(eventType) 1796 } 1797 1798 // EventFixture returns an event 1799 func EventFixture( 1800 eType flow.EventType, 1801 transactionIndex uint32, 1802 eventIndex uint32, 1803 txID flow.Identifier, 1804 _ int, 1805 ) flow.Event { 1806 return flow.Event{ 1807 Type: eType, 1808 TransactionIndex: transactionIndex, 1809 EventIndex: eventIndex, 1810 Payload: []byte{}, 1811 TransactionID: txID, 1812 } 1813 } 1814 1815 func EmulatorRootKey() (*flow.AccountPrivateKey, error) { 1816 1817 // TODO seems this key literal doesn't decode anymore 1818 emulatorRootKey, err := crypto.DecodePrivateKey(crypto.ECDSAP256, 1819 []byte("f87db87930770201010420ae2cc975dcbdd0ebc56f268b1d8a95834c2955970aea27042d35ec9f298b9e5aa00a06082a8648ce3d030107a1440342000417f5a527137785d2d773fee84b4c7ee40266a1dd1f36ddd46ecf25db6df6a499459629174de83256f2a44ebd4325b9def67d523b755a8926218c4efb7904f8ce0203")) 1820 if err != nil { 1821 return nil, err 1822 } 1823 1824 return &flow.AccountPrivateKey{ 1825 PrivateKey: emulatorRootKey, 1826 SignAlgo: emulatorRootKey.Algorithm(), 1827 HashAlgo: hash.SHA3_256, 1828 }, nil 1829 } 1830 1831 // NoopTxScript returns a Cadence script for a no-op transaction. 1832 func NoopTxScript() []byte { 1833 return []byte("transaction {}") 1834 } 1835 1836 func RangeFixture() chainsync.Range { 1837 return chainsync.Range{ 1838 From: rand.Uint64(), 1839 To: rand.Uint64(), 1840 } 1841 } 1842 1843 func BatchFixture() chainsync.Batch { 1844 return chainsync.Batch{ 1845 BlockIDs: IdentifierListFixture(10), 1846 } 1847 } 1848 1849 func RangeListFixture(n int) []chainsync.Range { 1850 if n <= 0 { 1851 return nil 1852 } 1853 ranges := make([]chainsync.Range, n) 1854 for i := range ranges { 1855 ranges[i] = RangeFixture() 1856 } 1857 return ranges 1858 } 1859 1860 func BatchListFixture(n int) []chainsync.Batch { 1861 if n <= 0 { 1862 return nil 1863 } 1864 batches := make([]chainsync.Batch, n) 1865 for i := range batches { 1866 batches[i] = BatchFixture() 1867 } 1868 return batches 1869 } 1870 1871 func BootstrapExecutionResultFixture( 1872 block *flow.Block, 1873 commit flow.StateCommitment, 1874 ) *flow.ExecutionResult { 1875 result := &flow.ExecutionResult{ 1876 BlockID: block.ID(), 1877 PreviousResultID: flow.ZeroID, 1878 Chunks: chunks.ChunkListFromCommit(commit), 1879 } 1880 return result 1881 } 1882 1883 func KeyFixture(algo crypto.SigningAlgorithm) crypto.PrivateKey { 1884 key, err := crypto.GeneratePrivateKey(algo, SeedFixture(128)) 1885 if err != nil { 1886 panic(err) 1887 } 1888 return key 1889 } 1890 1891 func KeysFixture(n int, algo crypto.SigningAlgorithm) []crypto.PrivateKey { 1892 keys := make([]crypto.PrivateKey, 0, n) 1893 for i := 0; i < n; i++ { 1894 keys = append(keys, KeyFixture(algo)) 1895 } 1896 return keys 1897 } 1898 1899 func PublicKeysFixture(n int, algo crypto.SigningAlgorithm) []crypto.PublicKey { 1900 pks := make([]crypto.PublicKey, 0, n) 1901 sks := KeysFixture(n, algo) 1902 for _, sk := range sks { 1903 pks = append(pks, sk.PublicKey()) 1904 } 1905 return pks 1906 } 1907 1908 func QuorumCertificateWithSignerIDsFixture(opts ...func(*flow.QuorumCertificateWithSignerIDs)) *flow.QuorumCertificateWithSignerIDs { 1909 qc := flow.QuorumCertificateWithSignerIDs{ 1910 View: uint64(rand.Uint32()), 1911 BlockID: IdentifierFixture(), 1912 SignerIDs: IdentifierListFixture(3), 1913 SigData: QCSigDataFixture(), 1914 } 1915 for _, apply := range opts { 1916 apply(&qc) 1917 } 1918 return &qc 1919 } 1920 1921 func QuorumCertificatesWithSignerIDsFixtures( 1922 n uint, 1923 opts ...func(*flow.QuorumCertificateWithSignerIDs), 1924 ) []*flow.QuorumCertificateWithSignerIDs { 1925 qcs := make([]*flow.QuorumCertificateWithSignerIDs, 0, n) 1926 for i := 0; i < int(n); i++ { 1927 qcs = append(qcs, QuorumCertificateWithSignerIDsFixture(opts...)) 1928 } 1929 return qcs 1930 } 1931 1932 func QuorumCertificatesFromAssignments(assignment flow.AssignmentList) []*flow.QuorumCertificateWithSignerIDs { 1933 qcs := make([]*flow.QuorumCertificateWithSignerIDs, 0, len(assignment)) 1934 for _, nodes := range assignment { 1935 qc := QuorumCertificateWithSignerIDsFixture() 1936 qc.SignerIDs = nodes 1937 qcs = append(qcs, qc) 1938 } 1939 return qcs 1940 } 1941 1942 func QuorumCertificateFixture(opts ...func(*flow.QuorumCertificate)) *flow.QuorumCertificate { 1943 qc := flow.QuorumCertificate{ 1944 View: uint64(rand.Uint32()), 1945 BlockID: IdentifierFixture(), 1946 SignerIndices: SignerIndicesFixture(3), 1947 SigData: QCSigDataFixture(), 1948 } 1949 for _, apply := range opts { 1950 apply(&qc) 1951 } 1952 return &qc 1953 } 1954 1955 // CertifyBlock returns a quorum certificate for the given block header 1956 func CertifyBlock(header *flow.Header) *flow.QuorumCertificate { 1957 qc := QuorumCertificateFixture(func(qc *flow.QuorumCertificate) { 1958 qc.View = header.View 1959 qc.BlockID = header.ID() 1960 }) 1961 return qc 1962 } 1963 1964 func QuorumCertificatesFixtures( 1965 n uint, 1966 opts ...func(*flow.QuorumCertificate), 1967 ) []*flow.QuorumCertificate { 1968 qcs := make([]*flow.QuorumCertificate, 0, n) 1969 for i := 0; i < int(n); i++ { 1970 qcs = append(qcs, QuorumCertificateFixture(opts...)) 1971 } 1972 return qcs 1973 } 1974 1975 func QCWithBlockID(blockID flow.Identifier) func(*flow.QuorumCertificate) { 1976 return func(qc *flow.QuorumCertificate) { 1977 qc.BlockID = blockID 1978 } 1979 } 1980 1981 func QCWithSignerIndices(signerIndices []byte) func(*flow.QuorumCertificate) { 1982 return func(qc *flow.QuorumCertificate) { 1983 qc.SignerIndices = signerIndices 1984 } 1985 } 1986 1987 func QCWithRootBlockID(blockID flow.Identifier) func(*flow.QuorumCertificate) { 1988 return func(qc *flow.QuorumCertificate) { 1989 qc.BlockID = blockID 1990 qc.View = 0 1991 } 1992 } 1993 1994 func VoteFixture(opts ...func(vote *hotstuff.Vote)) *hotstuff.Vote { 1995 vote := &hotstuff.Vote{ 1996 View: uint64(rand.Uint32()), 1997 BlockID: IdentifierFixture(), 1998 SignerID: IdentifierFixture(), 1999 SigData: RandomBytes(128), 2000 } 2001 2002 for _, opt := range opts { 2003 opt(vote) 2004 } 2005 2006 return vote 2007 } 2008 2009 func WithVoteSignerID(signerID flow.Identifier) func(*hotstuff.Vote) { 2010 return func(vote *hotstuff.Vote) { 2011 vote.SignerID = signerID 2012 } 2013 } 2014 2015 func WithVoteView(view uint64) func(*hotstuff.Vote) { 2016 return func(vote *hotstuff.Vote) { 2017 vote.View = view 2018 } 2019 } 2020 2021 func WithVoteBlockID(blockID flow.Identifier) func(*hotstuff.Vote) { 2022 return func(vote *hotstuff.Vote) { 2023 vote.BlockID = blockID 2024 } 2025 } 2026 2027 func VoteForBlockFixture( 2028 block *hotstuff.Block, 2029 opts ...func(vote *hotstuff.Vote), 2030 ) *hotstuff.Vote { 2031 vote := VoteFixture(WithVoteView(block.View), 2032 WithVoteBlockID(block.BlockID)) 2033 2034 for _, opt := range opts { 2035 opt(vote) 2036 } 2037 2038 return vote 2039 } 2040 2041 func VoteWithStakingSig() func(*hotstuff.Vote) { 2042 return func(vote *hotstuff.Vote) { 2043 vote.SigData = append([]byte{byte(encoding.SigTypeStaking)}, vote.SigData...) 2044 } 2045 } 2046 2047 func VoteWithBeaconSig() func(*hotstuff.Vote) { 2048 return func(vote *hotstuff.Vote) { 2049 vote.SigData = append([]byte{byte(encoding.SigTypeRandomBeacon)}, vote.SigData...) 2050 } 2051 } 2052 2053 func WithParticipants(participants flow.IdentitySkeletonList) func(*flow.EpochSetup) { 2054 return func(setup *flow.EpochSetup) { 2055 setup.Participants = participants.Sort(flow.Canonical[flow.IdentitySkeleton]) 2056 setup.Assignments = ClusterAssignment(1, participants.ToSkeleton()) 2057 } 2058 } 2059 2060 func SetupWithCounter(counter uint64) func(*flow.EpochSetup) { 2061 return func(setup *flow.EpochSetup) { 2062 setup.Counter = counter 2063 } 2064 } 2065 2066 func WithFinalView(view uint64) func(*flow.EpochSetup) { 2067 return func(setup *flow.EpochSetup) { 2068 setup.FinalView = view 2069 } 2070 } 2071 2072 func WithFirstView(view uint64) func(*flow.EpochSetup) { 2073 return func(setup *flow.EpochSetup) { 2074 setup.FirstView = view 2075 } 2076 } 2077 2078 // EpochSetupFixture creates a valid EpochSetup with default properties for 2079 // testing. The default properties can be overwritten with optional parameter 2080 // functions. 2081 func EpochSetupFixture(opts ...func(setup *flow.EpochSetup)) *flow.EpochSetup { 2082 participants := IdentityListFixture(5, WithAllRoles()) 2083 setup := &flow.EpochSetup{ 2084 Counter: uint64(rand.Uint32()), 2085 FirstView: uint64(0), 2086 FinalView: uint64(rand.Uint32() + 1000), 2087 Participants: participants.Sort(flow.Canonical[flow.Identity]).ToSkeleton(), 2088 RandomSource: SeedFixture(flow.EpochSetupRandomSourceLength), 2089 DKGPhase1FinalView: 100, 2090 DKGPhase2FinalView: 200, 2091 DKGPhase3FinalView: 300, 2092 TargetDuration: 60 * 60, 2093 TargetEndTime: uint64(time.Now().Add(time.Hour).Unix()), 2094 } 2095 for _, apply := range opts { 2096 apply(setup) 2097 } 2098 if setup.Assignments == nil { 2099 setup.Assignments = ClusterAssignment(1, setup.Participants) 2100 } 2101 return setup 2102 } 2103 2104 func IndexFixture() *flow.Index { 2105 return &flow.Index{ 2106 CollectionIDs: IdentifierListFixture(5), 2107 SealIDs: IdentifierListFixture(5), 2108 ReceiptIDs: IdentifierListFixture(5), 2109 } 2110 } 2111 2112 func WithDKGFromParticipants(participants flow.IdentitySkeletonList) func(*flow.EpochCommit) { 2113 count := len(participants.Filter(filter.IsValidDKGParticipant)) 2114 return func(commit *flow.EpochCommit) { 2115 commit.DKGParticipantKeys = PublicKeysFixture(count, crypto.BLSBLS12381) 2116 } 2117 } 2118 2119 func WithClusterQCsFromAssignments(assignments flow.AssignmentList) func(*flow.EpochCommit) { 2120 qcs := make([]*flow.QuorumCertificateWithSignerIDs, 0, len(assignments)) 2121 for _, assignment := range assignments { 2122 qcWithSignerIndex := QuorumCertificateWithSignerIDsFixture() 2123 qcWithSignerIndex.SignerIDs = assignment 2124 qcs = append(qcs, qcWithSignerIndex) 2125 } 2126 return func(commit *flow.EpochCommit) { 2127 commit.ClusterQCs = flow.ClusterQCVoteDatasFromQCs(qcs) 2128 } 2129 } 2130 2131 func DKGParticipantLookup(participants flow.IdentitySkeletonList) map[flow.Identifier]flow.DKGParticipant { 2132 lookup := make(map[flow.Identifier]flow.DKGParticipant) 2133 for i, node := range participants.Filter(filter.HasRole[flow.IdentitySkeleton](flow.RoleConsensus)) { 2134 lookup[node.NodeID] = flow.DKGParticipant{ 2135 Index: uint(i), 2136 KeyShare: KeyFixture(crypto.BLSBLS12381).PublicKey(), 2137 } 2138 } 2139 return lookup 2140 } 2141 2142 func CommitWithCounter(counter uint64) func(*flow.EpochCommit) { 2143 return func(commit *flow.EpochCommit) { 2144 commit.Counter = counter 2145 } 2146 } 2147 2148 func EpochCommitFixture(opts ...func(*flow.EpochCommit)) *flow.EpochCommit { 2149 commit := &flow.EpochCommit{ 2150 Counter: uint64(rand.Uint32()), 2151 ClusterQCs: flow.ClusterQCVoteDatasFromQCs(QuorumCertificatesWithSignerIDsFixtures(1)), 2152 DKGGroupKey: KeyFixture(crypto.BLSBLS12381).PublicKey(), 2153 DKGParticipantKeys: PublicKeysFixture(2, crypto.BLSBLS12381), 2154 } 2155 for _, apply := range opts { 2156 apply(commit) 2157 } 2158 return commit 2159 } 2160 2161 func WithBoundaries(boundaries ...flow.VersionBoundary) func(*flow.VersionBeacon) { 2162 return func(b *flow.VersionBeacon) { 2163 b.VersionBoundaries = append(b.VersionBoundaries, boundaries...) 2164 } 2165 } 2166 2167 func VersionBeaconFixture(options ...func(*flow.VersionBeacon)) *flow.VersionBeacon { 2168 2169 versionTable := &flow.VersionBeacon{ 2170 VersionBoundaries: []flow.VersionBoundary{}, 2171 Sequence: uint64(0), 2172 } 2173 opts := options 2174 2175 if len(opts) == 0 { 2176 opts = []func(*flow.VersionBeacon){ 2177 WithBoundaries(flow.VersionBoundary{ 2178 Version: "0.0.0", 2179 BlockHeight: 0, 2180 }), 2181 } 2182 } 2183 2184 for _, apply := range opts { 2185 apply(versionTable) 2186 } 2187 2188 return versionTable 2189 } 2190 2191 func ProtocolStateVersionUpgradeFixture() *flow.ProtocolStateVersionUpgrade { 2192 return &flow.ProtocolStateVersionUpgrade{ 2193 NewProtocolStateVersion: rand.Uint64(), 2194 ActiveView: rand.Uint64(), 2195 } 2196 } 2197 2198 // BootstrapFixture generates all the artifacts necessary to bootstrap the 2199 // protocol state. 2200 func BootstrapFixture( 2201 participants flow.IdentityList, 2202 opts ...func(*flow.Block), 2203 ) (*flow.Block, *flow.ExecutionResult, *flow.Seal) { 2204 return BootstrapFixtureWithChainID(participants, flow.Emulator, opts...) 2205 } 2206 2207 func BootstrapFixtureWithChainID( 2208 participants flow.IdentityList, 2209 chainID flow.ChainID, 2210 opts ...func(*flow.Block), 2211 ) (*flow.Block, *flow.ExecutionResult, *flow.Seal) { 2212 2213 root := flow.Genesis(chainID) 2214 for _, apply := range opts { 2215 apply(root) 2216 } 2217 2218 counter := uint64(1) 2219 setup := EpochSetupFixture( 2220 WithParticipants(participants.ToSkeleton()), 2221 SetupWithCounter(counter), 2222 WithFirstView(root.Header.View), 2223 WithFinalView(root.Header.View+100_000), 2224 ) 2225 commit := EpochCommitFixture( 2226 CommitWithCounter(counter), 2227 WithClusterQCsFromAssignments(setup.Assignments), 2228 WithDKGFromParticipants(participants.ToSkeleton()), 2229 ) 2230 2231 rootEpochState := inmem.ProtocolStateFromEpochServiceEvents(setup, commit) 2232 rootProtocolStateID := kvstore.NewDefaultKVStore(rootEpochState.ID()).ID() 2233 root.SetPayload(flow.Payload{ProtocolStateID: rootProtocolStateID}) 2234 stateCommit := GenesisStateCommitmentByChainID(chainID) 2235 2236 result := BootstrapExecutionResultFixture(root, stateCommit) 2237 result.ServiceEvents = []flow.ServiceEvent{ 2238 setup.ServiceEvent(), 2239 commit.ServiceEvent(), 2240 } 2241 2242 seal := Seal.Fixture(Seal.WithResult(result)) 2243 2244 return root, result, seal 2245 } 2246 2247 // RootSnapshotFixture returns a snapshot representing a root chain state, for 2248 // example one as returned from BootstrapFixture. 2249 func RootSnapshotFixture( 2250 participants flow.IdentityList, 2251 opts ...func(*flow.Block), 2252 ) *inmem.Snapshot { 2253 return RootSnapshotFixtureWithChainID(participants, flow.Emulator, opts...) 2254 } 2255 2256 func RootSnapshotFixtureWithChainID( 2257 participants flow.IdentityList, 2258 chainID flow.ChainID, 2259 opts ...func(*flow.Block), 2260 ) *inmem.Snapshot { 2261 block, result, seal := BootstrapFixtureWithChainID(participants.Sort(flow.Canonical[flow.Identity]), chainID, opts...) 2262 qc := QuorumCertificateFixture(QCWithRootBlockID(block.ID())) 2263 root, err := inmem.SnapshotFromBootstrapState(block, result, seal, qc) 2264 if err != nil { 2265 panic(err) 2266 } 2267 return root 2268 } 2269 2270 func SnapshotClusterByIndex( 2271 snapshot *inmem.Snapshot, 2272 clusterIndex uint, 2273 ) (protocol.Cluster, error) { 2274 epochs := snapshot.Epochs() 2275 epoch := epochs.Current() 2276 cluster, err := epoch.Cluster(clusterIndex) 2277 if err != nil { 2278 return nil, err 2279 } 2280 return cluster, nil 2281 } 2282 2283 // ChainFixture creates a list of blocks that forms a chain 2284 func ChainFixture(nonGenesisCount int) ( 2285 []*flow.Block, 2286 *flow.ExecutionResult, 2287 *flow.Seal, 2288 ) { 2289 chain := make([]*flow.Block, 0, nonGenesisCount+1) 2290 2291 participants := IdentityListFixture(5, WithAllRoles()) 2292 genesis, result, seal := BootstrapFixture(participants) 2293 chain = append(chain, genesis) 2294 2295 children := ChainFixtureFrom(nonGenesisCount, genesis.Header) 2296 chain = append(chain, children...) 2297 return chain, result, seal 2298 } 2299 2300 // ChainFixtureFrom creates a chain of blocks starting from a given parent block, 2301 // the total number of blocks in the chain is specified by the given count 2302 func ChainFixtureFrom(count int, parent *flow.Header) []*flow.Block { 2303 blocks := make([]*flow.Block, 0, count) 2304 2305 for i := 0; i < count; i++ { 2306 block := BlockWithParentFixture(parent) 2307 blocks = append(blocks, block) 2308 parent = block.Header 2309 } 2310 2311 return blocks 2312 } 2313 2314 func ReceiptChainFor( 2315 blocks []*flow.Block, 2316 result0 *flow.ExecutionResult, 2317 ) []*flow.ExecutionReceipt { 2318 receipts := make([]*flow.ExecutionReceipt, len(blocks)) 2319 receipts[0] = ExecutionReceiptFixture(WithResult(result0)) 2320 receipts[0].ExecutionResult.BlockID = blocks[0].ID() 2321 2322 for i := 1; i < len(blocks); i++ { 2323 b := blocks[i] 2324 prevReceipt := receipts[i-1] 2325 receipt := ReceiptForBlockFixture(b) 2326 receipt.ExecutionResult.PreviousResultID = prevReceipt.ExecutionResult.ID() 2327 prevLastChunk := prevReceipt.ExecutionResult.Chunks[len(prevReceipt.ExecutionResult.Chunks)-1] 2328 receipt.ExecutionResult.Chunks[0].StartState = prevLastChunk.EndState 2329 receipts[i] = receipt 2330 } 2331 2332 return receipts 2333 } 2334 2335 // ReconnectBlocksAndReceipts re-computes each block's PayloadHash and ParentID 2336 // so that all the blocks are connected. 2337 // blocks' height have to be in strict increasing order. 2338 func ReconnectBlocksAndReceipts(blocks []*flow.Block, receipts []*flow.ExecutionReceipt) { 2339 for i := 1; i < len(blocks); i++ { 2340 b := blocks[i] 2341 p := i - 1 2342 prev := blocks[p] 2343 if prev.Header.Height+1 != b.Header.Height { 2344 panic(fmt.Sprintf("height has gap when connecting blocks: expect %v, but got %v", prev.Header.Height+1, b.Header.Height)) 2345 } 2346 b.Header.ParentID = prev.ID() 2347 b.Header.PayloadHash = b.Payload.Hash() 2348 receipts[i].ExecutionResult.BlockID = b.ID() 2349 prevReceipt := receipts[p] 2350 receipts[i].ExecutionResult.PreviousResultID = prevReceipt.ExecutionResult.ID() 2351 for _, c := range receipts[i].ExecutionResult.Chunks { 2352 c.BlockID = b.ID() 2353 } 2354 } 2355 2356 // after changing results we need to update IDs of results in receipt 2357 for _, block := range blocks { 2358 if len(block.Payload.Results) > 0 { 2359 for i := range block.Payload.Receipts { 2360 block.Payload.Receipts[i].ResultID = block.Payload.Results[i].ID() 2361 } 2362 } 2363 } 2364 } 2365 2366 // DKGMessageFixture creates a single DKG message with random fields 2367 func DKGMessageFixture() *messages.DKGMessage { 2368 return &messages.DKGMessage{ 2369 Data: RandomBytes(10), 2370 DKGInstanceID: fmt.Sprintf("test-dkg-instance-%d", uint64(rand.Int())), 2371 } 2372 } 2373 2374 // DKGBroadcastMessageFixture creates a single DKG broadcast message with random fields 2375 func DKGBroadcastMessageFixture() *messages.BroadcastDKGMessage { 2376 return &messages.BroadcastDKGMessage{ 2377 DKGMessage: *DKGMessageFixture(), 2378 CommitteeMemberIndex: uint64(rand.Int()), 2379 NodeID: IdentifierFixture(), 2380 Signature: SignatureFixture(), 2381 } 2382 } 2383 2384 // PrivateKeyFixture returns a random private key with specified signature algorithm and seed length 2385 func PrivateKeyFixture(algo crypto.SigningAlgorithm, seedLength int) crypto.PrivateKey { 2386 sk, err := crypto.GeneratePrivateKey(algo, SeedFixture(seedLength)) 2387 if err != nil { 2388 panic(err) 2389 } 2390 return sk 2391 } 2392 2393 // PrivateKeyFixtureByIdentifier returns a private key for a given node. 2394 // given the same identifier, it will always return the same private key 2395 func PrivateKeyFixtureByIdentifier( 2396 algo crypto.SigningAlgorithm, 2397 seedLength int, 2398 id flow.Identifier, 2399 ) crypto.PrivateKey { 2400 seed := append(id[:], id[:]...) 2401 sk, err := crypto.GeneratePrivateKey(algo, seed[:seedLength]) 2402 if err != nil { 2403 panic(err) 2404 } 2405 return sk 2406 } 2407 2408 func StakingPrivKeyByIdentifier(id flow.Identifier) crypto.PrivateKey { 2409 return PrivateKeyFixtureByIdentifier(crypto.BLSBLS12381, crypto.KeyGenSeedMinLen, id) 2410 } 2411 2412 // NetworkingPrivKeyFixture returns random ECDSAP256 private key 2413 func NetworkingPrivKeyFixture() crypto.PrivateKey { 2414 return PrivateKeyFixture(crypto.ECDSAP256, crypto.KeyGenSeedMinLen) 2415 } 2416 2417 // StakingPrivKeyFixture returns a random BLS12381 private keyf 2418 func StakingPrivKeyFixture() crypto.PrivateKey { 2419 return PrivateKeyFixture(crypto.BLSBLS12381, crypto.KeyGenSeedMinLen) 2420 } 2421 2422 func NodeMachineAccountInfoFixture() bootstrap.NodeMachineAccountInfo { 2423 return bootstrap.NodeMachineAccountInfo{ 2424 Address: RandomAddressFixture().String(), 2425 EncodedPrivateKey: PrivateKeyFixture(crypto.ECDSAP256, DefaultSeedFixtureLength).Encode(), 2426 HashAlgorithm: bootstrap.DefaultMachineAccountHashAlgo, 2427 SigningAlgorithm: bootstrap.DefaultMachineAccountSignAlgo, 2428 KeyIndex: bootstrap.DefaultMachineAccountKeyIndex, 2429 } 2430 } 2431 2432 func MachineAccountFixture(t *testing.T) ( 2433 bootstrap.NodeMachineAccountInfo, 2434 *sdk.Account, 2435 ) { 2436 info := NodeMachineAccountInfoFixture() 2437 2438 bal, err := cadence.NewUFix64("0.5") 2439 require.NoError(t, err) 2440 2441 acct := &sdk.Account{ 2442 Address: sdk.HexToAddress(info.Address), 2443 Balance: uint64(bal), 2444 Keys: []*sdk.AccountKey{ 2445 { 2446 Index: int(info.KeyIndex), 2447 PublicKey: info.MustPrivateKey().PublicKey(), 2448 SigAlgo: info.SigningAlgorithm, 2449 HashAlgo: info.HashAlgorithm, 2450 Weight: 1000, 2451 }, 2452 }, 2453 } 2454 return info, acct 2455 } 2456 2457 func TransactionResultsFixture(n int) []flow.TransactionResult { 2458 results := make([]flow.TransactionResult, 0, n) 2459 for i := 0; i < n; i++ { 2460 results = append(results, flow.TransactionResult{ 2461 TransactionID: IdentifierFixture(), 2462 ErrorMessage: "whatever", 2463 ComputationUsed: uint64(rand.Uint32()), 2464 }) 2465 } 2466 return results 2467 } 2468 2469 func LightTransactionResultsFixture(n int) []flow.LightTransactionResult { 2470 results := make([]flow.LightTransactionResult, 0, n) 2471 for i := 0; i < n; i++ { 2472 results = append(results, flow.LightTransactionResult{ 2473 TransactionID: IdentifierFixture(), 2474 Failed: i%2 == 0, 2475 ComputationUsed: Uint64InRange(1, 10_000), 2476 }) 2477 } 2478 return results 2479 } 2480 2481 func AllowAllPeerFilter() func(peer.ID) error { 2482 return func(_ peer.ID) error { 2483 return nil 2484 } 2485 } 2486 2487 func NewSealingConfigs(val uint) module.SealingConfigsSetter { 2488 instance, err := updatable_configs.NewSealingConfigs( 2489 flow.DefaultRequiredApprovalsForSealConstruction, 2490 flow.DefaultRequiredApprovalsForSealValidation, 2491 flow.DefaultChunkAssignmentAlpha, 2492 flow.DefaultEmergencySealingActive, 2493 ) 2494 if err != nil { 2495 panic(err) 2496 } 2497 err = instance.SetRequiredApprovalsForSealingConstruction(val) 2498 if err != nil { 2499 panic(err) 2500 } 2501 return instance 2502 } 2503 2504 func PeerIDFromFlowID(identity *flow.Identity) (peer.ID, error) { 2505 networkKey := identity.NetworkPubKey 2506 peerPK, err := keyutils.LibP2PPublicKeyFromFlow(networkKey) 2507 if err != nil { 2508 return "", err 2509 } 2510 2511 peerID, err := peer.IDFromPublicKey(peerPK) 2512 if err != nil { 2513 return "", err 2514 } 2515 2516 return peerID, nil 2517 } 2518 2519 func EngineMessageFixture() *engine.Message { 2520 return &engine.Message{ 2521 OriginID: IdentifierFixture(), 2522 Payload: RandomBytes(10), 2523 } 2524 } 2525 2526 func EngineMessageFixtures(count int) []*engine.Message { 2527 messages := make([]*engine.Message, 0, count) 2528 for i := 0; i < count; i++ { 2529 messages = append(messages, EngineMessageFixture()) 2530 } 2531 return messages 2532 } 2533 2534 // GetFlowProtocolEventID returns the event ID for the event provided. 2535 func GetFlowProtocolEventID( 2536 t *testing.T, 2537 channel channels.Channel, 2538 event interface{}, 2539 ) flow.Identifier { 2540 payload, err := NetworkCodec().Encode(event) 2541 require.NoError(t, err) 2542 eventIDHash, err := message.EventId(channel, payload) 2543 require.NoError(t, err) 2544 return flow.HashToID(eventIDHash) 2545 } 2546 2547 func WithBlockExecutionDataBlockID(blockID flow.Identifier) func(*execution_data.BlockExecutionData) { 2548 return func(bed *execution_data.BlockExecutionData) { 2549 bed.BlockID = blockID 2550 } 2551 } 2552 2553 func WithChunkExecutionDatas(chunks ...*execution_data.ChunkExecutionData) func(*execution_data.BlockExecutionData) { 2554 return func(bed *execution_data.BlockExecutionData) { 2555 bed.ChunkExecutionDatas = chunks 2556 } 2557 } 2558 2559 func BlockExecutionDataFixture(opts ...func(*execution_data.BlockExecutionData)) *execution_data.BlockExecutionData { 2560 bed := &execution_data.BlockExecutionData{ 2561 BlockID: IdentifierFixture(), 2562 ChunkExecutionDatas: []*execution_data.ChunkExecutionData{}, 2563 } 2564 2565 for _, opt := range opts { 2566 opt(bed) 2567 } 2568 2569 return bed 2570 } 2571 2572 func BlockExecutionDatEntityFixture(opts ...func(*execution_data.BlockExecutionData)) *execution_data.BlockExecutionDataEntity { 2573 execData := BlockExecutionDataFixture(opts...) 2574 return execution_data.NewBlockExecutionDataEntity(IdentifierFixture(), execData) 2575 } 2576 2577 func BlockExecutionDatEntityListFixture(n int) []*execution_data.BlockExecutionDataEntity { 2578 l := make([]*execution_data.BlockExecutionDataEntity, n) 2579 for i := 0; i < n; i++ { 2580 l[i] = BlockExecutionDatEntityFixture() 2581 } 2582 2583 return l 2584 } 2585 2586 func WithChunkEvents(events flow.EventsList) func(*execution_data.ChunkExecutionData) { 2587 return func(conf *execution_data.ChunkExecutionData) { 2588 conf.Events = events 2589 } 2590 } 2591 2592 func WithTrieUpdate(trieUpdate *ledger.TrieUpdate) func(*execution_data.ChunkExecutionData) { 2593 return func(conf *execution_data.ChunkExecutionData) { 2594 conf.TrieUpdate = trieUpdate 2595 } 2596 } 2597 2598 func ChunkExecutionDataFixture(t *testing.T, minSize int, opts ...func(*execution_data.ChunkExecutionData)) *execution_data.ChunkExecutionData { 2599 collection := CollectionFixture(5) 2600 results := make([]flow.LightTransactionResult, len(collection.Transactions)) 2601 for i, tx := range collection.Transactions { 2602 results[i] = flow.LightTransactionResult{ 2603 TransactionID: tx.ID(), 2604 Failed: false, 2605 ComputationUsed: uint64(i * 100), 2606 } 2607 } 2608 2609 ced := &execution_data.ChunkExecutionData{ 2610 Collection: &collection, 2611 Events: nil, 2612 TrieUpdate: testutils.TrieUpdateFixture(2, 1, 8), 2613 TransactionResults: results, 2614 } 2615 2616 for _, opt := range opts { 2617 opt(ced) 2618 } 2619 2620 if minSize <= 1 || ced.TrieUpdate == nil { 2621 return ced 2622 } 2623 2624 size := 1 2625 for { 2626 buf := &bytes.Buffer{} 2627 require.NoError(t, execution_data.DefaultSerializer.Serialize(buf, ced)) 2628 if buf.Len() >= minSize { 2629 return ced 2630 } 2631 2632 v := make([]byte, size) 2633 _, err := crand.Read(v) 2634 require.NoError(t, err) 2635 2636 k, err := ced.TrieUpdate.Payloads[0].Key() 2637 require.NoError(t, err) 2638 2639 ced.TrieUpdate.Payloads[0] = ledger.NewPayload(k, v) 2640 size *= 2 2641 } 2642 } 2643 2644 // RootProtocolStateFixture creates a fixture with correctly structured data for root protocol state. 2645 // This can be useful for testing bootstrap when there is no previous epoch. 2646 func RootProtocolStateFixture() *flow.RichProtocolStateEntry { 2647 currentEpochSetup := EpochSetupFixture(func(setup *flow.EpochSetup) { 2648 setup.Counter = 1 2649 }) 2650 currentEpochCommit := EpochCommitFixture(func(commit *flow.EpochCommit) { 2651 commit.Counter = currentEpochSetup.Counter 2652 }) 2653 2654 allIdentities := make(flow.IdentityList, 0, len(currentEpochSetup.Participants)) 2655 for _, identity := range currentEpochSetup.Participants { 2656 allIdentities = append(allIdentities, &flow.Identity{ 2657 IdentitySkeleton: *identity, 2658 DynamicIdentity: flow.DynamicIdentity{ 2659 EpochParticipationStatus: flow.EpochParticipationStatusActive, 2660 }, 2661 }) 2662 } 2663 return &flow.RichProtocolStateEntry{ 2664 ProtocolStateEntry: &flow.ProtocolStateEntry{ 2665 PreviousEpoch: nil, 2666 CurrentEpoch: flow.EpochStateContainer{ 2667 SetupID: currentEpochSetup.ID(), 2668 CommitID: currentEpochCommit.ID(), 2669 ActiveIdentities: flow.DynamicIdentityEntryListFromIdentities(allIdentities), 2670 }, 2671 InvalidEpochTransitionAttempted: false, 2672 NextEpoch: nil, 2673 }, 2674 PreviousEpochSetup: nil, 2675 PreviousEpochCommit: nil, 2676 CurrentEpochSetup: currentEpochSetup, 2677 CurrentEpochCommit: currentEpochCommit, 2678 NextEpochSetup: nil, 2679 NextEpochCommit: nil, 2680 CurrentEpochIdentityTable: allIdentities, 2681 NextEpochIdentityTable: flow.IdentityList{}, 2682 } 2683 } 2684 2685 // EpochStateFixture creates a fixture with correctly structured data. The returned Identity Table 2686 // represents the common situation during the staking phase of Epoch N+1: 2687 // - we are currently in Epoch N 2688 // - previous epoch N-1 is known (specifically EpochSetup and EpochCommit events) 2689 // - network is currently in the staking phase to setup the next epoch, hence no service 2690 // events for the next epoch exist 2691 // 2692 // In particular, the following consistency requirements hold: 2693 // - Epoch setup and commit counters are set to match. 2694 // - Identities are constructed from setup events. 2695 // - Identities are sorted in canonical order. 2696 func EpochStateFixture(options ...func(*flow.RichProtocolStateEntry)) *flow.RichProtocolStateEntry { 2697 prevEpochSetup := EpochSetupFixture() 2698 prevEpochCommit := EpochCommitFixture(func(commit *flow.EpochCommit) { 2699 commit.Counter = prevEpochSetup.Counter 2700 }) 2701 currentEpochSetup := EpochSetupFixture(func(setup *flow.EpochSetup) { 2702 setup.Counter = prevEpochSetup.Counter + 1 2703 // reuse same participant for current epoch 2704 sameParticipant := *prevEpochSetup.Participants[1] 2705 setup.Participants = append(setup.Participants, &sameParticipant) 2706 setup.Participants = setup.Participants.Sort(flow.Canonical[flow.IdentitySkeleton]) 2707 }) 2708 currentEpochCommit := EpochCommitFixture(func(commit *flow.EpochCommit) { 2709 commit.Counter = currentEpochSetup.Counter 2710 }) 2711 2712 buildDefaultIdentities := func(setup *flow.EpochSetup) flow.IdentityList { 2713 epochIdentities := make(flow.IdentityList, 0, len(setup.Participants)) 2714 for _, identity := range setup.Participants { 2715 epochIdentities = append(epochIdentities, &flow.Identity{ 2716 IdentitySkeleton: *identity, 2717 DynamicIdentity: flow.DynamicIdentity{ 2718 EpochParticipationStatus: flow.EpochParticipationStatusActive, 2719 }, 2720 }) 2721 } 2722 return epochIdentities.Sort(flow.Canonical[flow.Identity]) 2723 } 2724 2725 prevEpochIdentities := buildDefaultIdentities(prevEpochSetup) 2726 currentEpochIdentities := buildDefaultIdentities(currentEpochSetup) 2727 allIdentities := currentEpochIdentities.Union( 2728 prevEpochIdentities.Map(mapfunc.WithEpochParticipationStatus(flow.EpochParticipationStatusLeaving))) 2729 2730 entry := &flow.RichProtocolStateEntry{ 2731 ProtocolStateEntry: &flow.ProtocolStateEntry{ 2732 CurrentEpoch: flow.EpochStateContainer{ 2733 SetupID: currentEpochSetup.ID(), 2734 CommitID: currentEpochCommit.ID(), 2735 ActiveIdentities: flow.DynamicIdentityEntryListFromIdentities(currentEpochIdentities), 2736 }, 2737 PreviousEpoch: &flow.EpochStateContainer{ 2738 SetupID: prevEpochSetup.ID(), 2739 CommitID: prevEpochCommit.ID(), 2740 ActiveIdentities: flow.DynamicIdentityEntryListFromIdentities(prevEpochIdentities), 2741 }, 2742 InvalidEpochTransitionAttempted: false, 2743 NextEpoch: nil, 2744 }, 2745 PreviousEpochSetup: prevEpochSetup, 2746 PreviousEpochCommit: prevEpochCommit, 2747 CurrentEpochSetup: currentEpochSetup, 2748 CurrentEpochCommit: currentEpochCommit, 2749 NextEpochSetup: nil, 2750 NextEpochCommit: nil, 2751 CurrentEpochIdentityTable: allIdentities, 2752 NextEpochIdentityTable: flow.IdentityList{}, 2753 } 2754 2755 for _, option := range options { 2756 option(entry) 2757 } 2758 2759 return entry 2760 } 2761 2762 // WithNextEpochProtocolState creates a fixture with correctly structured data for next epoch. 2763 // The resulting Identity Table represents the common situation during the epoch commit phase for Epoch N+1: 2764 // - We are currently in Epoch N. 2765 // - The previous epoch N-1 is known (specifically EpochSetup and EpochCommit events). 2766 // - The network has completed the epoch setup phase, i.e. published the EpochSetup and EpochCommit events for epoch N+1. 2767 func WithNextEpochProtocolState() func(entry *flow.RichProtocolStateEntry) { 2768 return func(entry *flow.RichProtocolStateEntry) { 2769 nextEpochSetup := EpochSetupFixture(func(setup *flow.EpochSetup) { 2770 setup.Counter = entry.CurrentEpochSetup.Counter + 1 2771 setup.FirstView = entry.CurrentEpochSetup.FinalView + 1 2772 setup.FinalView = setup.FirstView + 1000 2773 // reuse same participant for current epoch 2774 sameParticipant := *entry.CurrentEpochSetup.Participants[1] 2775 setup.Participants[1] = &sameParticipant 2776 setup.Participants = setup.Participants.Sort(flow.Canonical[flow.IdentitySkeleton]) 2777 }) 2778 nextEpochCommit := EpochCommitFixture(func(commit *flow.EpochCommit) { 2779 commit.Counter = nextEpochSetup.Counter 2780 }) 2781 2782 nextEpochParticipants := make(flow.IdentityList, 0, len(nextEpochSetup.Participants)) 2783 for _, identity := range nextEpochSetup.Participants { 2784 nextEpochParticipants = append(nextEpochParticipants, &flow.Identity{ 2785 IdentitySkeleton: *identity, 2786 DynamicIdentity: flow.DynamicIdentity{ 2787 EpochParticipationStatus: flow.EpochParticipationStatusActive, 2788 }, 2789 }) 2790 } 2791 nextEpochParticipants = nextEpochParticipants.Sort(flow.Canonical[flow.Identity]) 2792 2793 currentEpochParticipants := entry.CurrentEpochIdentityTable.Filter(func(identity *flow.Identity) bool { 2794 _, found := entry.CurrentEpochSetup.Participants.ByNodeID(identity.NodeID) 2795 return found 2796 }).Sort(flow.Canonical[flow.Identity]) 2797 2798 entry.CurrentEpochIdentityTable = currentEpochParticipants.Union( 2799 nextEpochParticipants.Map(mapfunc.WithEpochParticipationStatus(flow.EpochParticipationStatusJoining))) 2800 entry.NextEpochIdentityTable = nextEpochParticipants.Union( 2801 currentEpochParticipants.Map(mapfunc.WithEpochParticipationStatus(flow.EpochParticipationStatusLeaving))) 2802 2803 entry.NextEpoch = &flow.EpochStateContainer{ 2804 SetupID: nextEpochSetup.ID(), 2805 CommitID: nextEpochCommit.ID(), 2806 ActiveIdentities: flow.DynamicIdentityEntryListFromIdentities(nextEpochParticipants), 2807 } 2808 entry.NextEpochSetup = nextEpochSetup 2809 entry.NextEpochCommit = nextEpochCommit 2810 } 2811 } 2812 2813 // WithValidDKG updated protocol state with correctly structured data for DKG. 2814 func WithValidDKG() func(*flow.RichProtocolStateEntry) { 2815 return func(entry *flow.RichProtocolStateEntry) { 2816 commit := entry.CurrentEpochCommit 2817 dkgParticipants := entry.CurrentEpochSetup.Participants.Filter(filter.IsValidDKGParticipant) 2818 lookup := DKGParticipantLookup(dkgParticipants) 2819 commit.DKGParticipantKeys = make([]crypto.PublicKey, len(lookup)) 2820 for _, participant := range lookup { 2821 commit.DKGParticipantKeys[participant.Index] = participant.KeyShare 2822 } 2823 } 2824 } 2825 2826 func CreateSendTxHttpPayload(tx flow.TransactionBody) map[string]interface{} { 2827 tx.Arguments = [][]uint8{} // fix how fixture creates nil values 2828 auth := make([]string, len(tx.Authorizers)) 2829 for i, a := range tx.Authorizers { 2830 auth[i] = a.String() 2831 } 2832 2833 return map[string]interface{}{ 2834 "script": util.ToBase64(tx.Script), 2835 "arguments": tx.Arguments, 2836 "reference_block_id": tx.ReferenceBlockID.String(), 2837 "gas_limit": fmt.Sprintf("%d", tx.GasLimit), 2838 "payer": tx.Payer.String(), 2839 "proposal_key": map[string]interface{}{ 2840 "address": tx.ProposalKey.Address.String(), 2841 "key_index": fmt.Sprintf("%d", tx.ProposalKey.KeyIndex), 2842 "sequence_number": fmt.Sprintf("%d", tx.ProposalKey.SequenceNumber), 2843 }, 2844 "authorizers": auth, 2845 "payload_signatures": []map[string]interface{}{{ 2846 "address": tx.PayloadSignatures[0].Address.String(), 2847 "key_index": fmt.Sprintf("%d", tx.PayloadSignatures[0].KeyIndex), 2848 "signature": util.ToBase64(tx.PayloadSignatures[0].Signature), 2849 }}, 2850 "envelope_signatures": []map[string]interface{}{{ 2851 "address": tx.EnvelopeSignatures[0].Address.String(), 2852 "key_index": fmt.Sprintf("%d", tx.EnvelopeSignatures[0].KeyIndex), 2853 "signature": util.ToBase64(tx.EnvelopeSignatures[0].Signature), 2854 }}, 2855 } 2856 } 2857 2858 // P2PRPCGraftFixtures returns n number of control message rpc Graft fixtures. 2859 func P2PRPCGraftFixtures(topics ...string) []*pubsub_pb.ControlGraft { 2860 n := len(topics) 2861 grafts := make([]*pubsub_pb.ControlGraft, n) 2862 for i := 0; i < n; i++ { 2863 grafts[i] = P2PRPCGraftFixture(&topics[i]) 2864 } 2865 return grafts 2866 } 2867 2868 // P2PRPCGraftFixture returns a control message rpc Graft fixture. 2869 func P2PRPCGraftFixture(topic *string) *pubsub_pb.ControlGraft { 2870 return &pubsub_pb.ControlGraft{ 2871 TopicID: topic, 2872 } 2873 } 2874 2875 // P2PRPCPruneFixtures returns n number of control message rpc Prune fixtures. 2876 func P2PRPCPruneFixtures(topics ...string) []*pubsub_pb.ControlPrune { 2877 n := len(topics) 2878 prunes := make([]*pubsub_pb.ControlPrune, n) 2879 for i := 0; i < n; i++ { 2880 prunes[i] = P2PRPCPruneFixture(&topics[i]) 2881 } 2882 return prunes 2883 } 2884 2885 // P2PRPCPruneFixture returns a control message rpc Prune fixture. 2886 func P2PRPCPruneFixture(topic *string) *pubsub_pb.ControlPrune { 2887 return &pubsub_pb.ControlPrune{ 2888 TopicID: topic, 2889 } 2890 } 2891 2892 // P2PRPCIHaveFixtures returns n number of control message where n = len(topics) rpc iHave fixtures with m number of message ids each. 2893 func P2PRPCIHaveFixtures(m int, topics ...string) []*pubsub_pb.ControlIHave { 2894 n := len(topics) 2895 ihaves := make([]*pubsub_pb.ControlIHave, n) 2896 for i := 0; i < n; i++ { 2897 ihaves[i] = P2PRPCIHaveFixture(&topics[i], IdentifierListFixture(m).Strings()...) 2898 } 2899 return ihaves 2900 } 2901 2902 // P2PRPCIHaveFixture returns a control message rpc iHave fixture. 2903 func P2PRPCIHaveFixture(topic *string, messageIds ...string) *pubsub_pb.ControlIHave { 2904 return &pubsub_pb.ControlIHave{ 2905 TopicID: topic, 2906 MessageIDs: messageIds, 2907 } 2908 } 2909 2910 // P2PRPCIWantFixtures returns n number of control message rpc iWant fixtures with m number of message ids each. 2911 func P2PRPCIWantFixtures(n, m int) []*pubsub_pb.ControlIWant { 2912 iwants := make([]*pubsub_pb.ControlIWant, n) 2913 for i := 0; i < n; i++ { 2914 iwants[i] = P2PRPCIWantFixture(IdentifierListFixture(m).Strings()...) 2915 } 2916 return iwants 2917 } 2918 2919 // P2PRPCIWantFixture returns a control message rpc iWant fixture. 2920 func P2PRPCIWantFixture(messageIds ...string) *pubsub_pb.ControlIWant { 2921 return &pubsub_pb.ControlIWant{ 2922 MessageIDs: messageIds, 2923 } 2924 } 2925 2926 type RPCFixtureOpt func(rpc *pubsub.RPC) 2927 2928 // WithGrafts sets the grafts on the rpc control message. 2929 func WithGrafts(grafts ...*pubsub_pb.ControlGraft) RPCFixtureOpt { 2930 return func(rpc *pubsub.RPC) { 2931 rpc.Control.Graft = grafts 2932 } 2933 } 2934 2935 // WithPrunes sets the prunes on the rpc control message. 2936 func WithPrunes(prunes ...*pubsub_pb.ControlPrune) RPCFixtureOpt { 2937 return func(rpc *pubsub.RPC) { 2938 rpc.Control.Prune = prunes 2939 } 2940 } 2941 2942 // WithIHaves sets the iHaves on the rpc control message. 2943 func WithIHaves(iHaves ...*pubsub_pb.ControlIHave) RPCFixtureOpt { 2944 return func(rpc *pubsub.RPC) { 2945 rpc.Control.Ihave = iHaves 2946 } 2947 } 2948 2949 // WithIWants sets the iWants on the rpc control message. 2950 func WithIWants(iWants ...*pubsub_pb.ControlIWant) RPCFixtureOpt { 2951 return func(rpc *pubsub.RPC) { 2952 rpc.Control.Iwant = iWants 2953 } 2954 } 2955 2956 func WithPubsubMessages(msgs ...*pubsub_pb.Message) RPCFixtureOpt { 2957 return func(rpc *pubsub.RPC) { 2958 rpc.Publish = msgs 2959 } 2960 } 2961 2962 // P2PRPCFixture returns a pubsub RPC fixture. Currently, this fixture only sets the ControlMessage field. 2963 func P2PRPCFixture(opts ...RPCFixtureOpt) *pubsub.RPC { 2964 rpc := &pubsub.RPC{ 2965 RPC: pubsub_pb.RPC{ 2966 Control: &pubsub_pb.ControlMessage{}, 2967 }, 2968 } 2969 2970 for _, opt := range opts { 2971 opt(rpc) 2972 } 2973 2974 return rpc 2975 } 2976 2977 func WithFrom(pid peer.ID) func(*pubsub_pb.Message) { 2978 return func(msg *pubsub_pb.Message) { 2979 msg.From = []byte(pid) 2980 } 2981 } 2982 2983 // GossipSubMessageFixture returns a gossip sub message fixture for the specified topic. 2984 func GossipSubMessageFixture(s string, opts ...func(*pubsub_pb.Message)) *pubsub_pb.Message { 2985 pb := &pubsub_pb.Message{ 2986 From: RandomBytes(32), 2987 Data: RandomBytes(32), 2988 Seqno: RandomBytes(10), 2989 Topic: &s, 2990 Signature: RandomBytes(100), 2991 Key: RandomBytes(32), 2992 } 2993 2994 for _, opt := range opts { 2995 opt(pb) 2996 } 2997 2998 return pb 2999 } 3000 3001 // GossipSubMessageFixtures returns a list of gossipsub message fixtures. 3002 func GossipSubMessageFixtures(n int, topic string, opts ...func(*pubsub_pb.Message)) []*pubsub_pb.Message { 3003 msgs := make([]*pubsub_pb.Message, n) 3004 for i := 0; i < n; i++ { 3005 msgs[i] = GossipSubMessageFixture(topic, opts...) 3006 } 3007 return msgs 3008 } 3009 3010 // LibP2PResourceLimitOverrideFixture returns a random resource limit override for testing. 3011 // The values are not guaranteed to be valid between 0 and 1000. 3012 // Returns: 3013 // - p2pconf.ResourceManagerOverrideLimit: a random resource limit override. 3014 func LibP2PResourceLimitOverrideFixture() p2pconfig.ResourceManagerOverrideLimit { 3015 return p2pconfig.ResourceManagerOverrideLimit{ 3016 StreamsInbound: rand.Intn(1000), 3017 StreamsOutbound: rand.Intn(1000), 3018 ConnectionsInbound: rand.Intn(1000), 3019 ConnectionsOutbound: rand.Intn(1000), 3020 FD: rand.Intn(1000), 3021 Memory: rand.Intn(1000), 3022 } 3023 } 3024 3025 func RegisterEntryFixture() flow.RegisterEntry { 3026 val := make([]byte, 4) 3027 _, _ = crand.Read(val) 3028 return flow.RegisterEntry{ 3029 Key: flow.RegisterID{ 3030 Owner: "owner", 3031 Key: "key1", 3032 }, 3033 Value: val, 3034 } 3035 } 3036 3037 func MakeOwnerReg(key string, value string) flow.RegisterEntry { 3038 return flow.RegisterEntry{ 3039 Key: flow.RegisterID{ 3040 Owner: "owner", 3041 Key: key, 3042 }, 3043 Value: []byte(value), 3044 } 3045 }