github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/mempool/entity/executableblock.go (about) 1 package entity 2 3 import ( 4 "github.com/onflow/flow-go/model/flow" 5 ) 6 7 // A complete collection contains the guarantee and the transactions. 8 // the guarantee is the hash of all the transactions. The execution node 9 // receives the guarantee from the block, and queries the transactions by 10 // the guarantee from the collection node. 11 // when receiving a collection from collection node, the execution node will 12 // update the Transactions field of a CompleteCollection and make it complete. 13 type CompleteCollection struct { 14 Guarantee *flow.CollectionGuarantee 15 Transactions []*flow.TransactionBody 16 } 17 18 // ExecutableBlock represents a block that can be executed by the VM 19 // 20 // It assumes that the Block attached is immutable, so take care in not modifying or changing the inner 21 // *flow.Block, otherwise the struct will be in an inconsistent state. It requires the Block is immutable 22 // because the it lazy lodas the Block.ID() into the private id field, on the first call to ExecutableBlock.ID() 23 // All future calls to ID will not call Block.ID(), therefore it Block changes, the id will not match the Block. 24 type ExecutableBlock struct { 25 id flow.Identifier 26 Block *flow.Block 27 CompleteCollections map[flow.Identifier]*CompleteCollection // key is the collection ID. 28 StartState *flow.StateCommitment 29 Executing bool // flag used to indicate if block is being executed, to avoid re-execution 30 } 31 32 // BlocksByCollection represents a collection that the execution node. 33 // has not received its transactions yet. 34 // it also holds references to the blocks that contains this collection 35 // and are waiting to be executed. 36 type BlocksByCollection struct { 37 CollectionID flow.Identifier 38 // a reversed map to look up which block contains this collection. key is the collection id 39 ExecutableBlocks map[flow.Identifier]*ExecutableBlock 40 } 41 42 func (c CompleteCollection) Collection() flow.Collection { 43 return flow.Collection{Transactions: c.Transactions} 44 } 45 46 func (c CompleteCollection) IsCompleted() bool { 47 return len(c.Transactions) > 0 48 } 49 50 func (b *BlocksByCollection) ID() flow.Identifier { 51 return b.CollectionID 52 } 53 54 func (b *BlocksByCollection) Checksum() flow.Identifier { 55 return b.CollectionID 56 } 57 58 // ID lazy loads the Block.ID() into the private id field on the first call, and returns 59 // the id field in all future calls 60 func (b *ExecutableBlock) ID() flow.Identifier { 61 if b.id == flow.ZeroID { 62 b.id = b.Block.ID() 63 } 64 return b.id 65 } 66 67 func (b *ExecutableBlock) Checksum() flow.Identifier { 68 return b.Block.Checksum() 69 } 70 71 func (b *ExecutableBlock) Height() uint64 { 72 return b.Block.Header.Height 73 } 74 75 func (b *ExecutableBlock) ParentID() flow.Identifier { 76 return b.Block.Header.ParentID 77 } 78 79 func (b *ExecutableBlock) Collections() []*CompleteCollection { 80 collections := make([]*CompleteCollection, len(b.Block.Payload.Guarantees)) 81 82 for i, cg := range b.Block.Payload.Guarantees { 83 collections[i] = b.CompleteCollections[cg.ID()] 84 } 85 86 return collections 87 } 88 89 // CompleteCollectionAt returns a complete collection at the given index, 90 // if index out of range, nil will be returned 91 func (b *ExecutableBlock) CompleteCollectionAt(index int) *CompleteCollection { 92 if index < 0 || index >= len(b.Block.Payload.Guarantees) { 93 return nil 94 } 95 return b.CompleteCollections[b.Block.Payload.Guarantees[index].ID()] 96 } 97 98 // CollectionAt returns a collection at the given index, 99 // if index out of range, nil will be returned 100 func (b *ExecutableBlock) CollectionAt(index int) *flow.Collection { 101 cc := b.CompleteCollectionAt(index) 102 if cc == nil { 103 return nil 104 } 105 return &flow.Collection{Transactions: cc.Transactions} 106 } 107 108 // HasAllTransactions returns whether all the transactions for all collections 109 // in the block have been received. 110 func (b *ExecutableBlock) HasAllTransactions() bool { 111 for _, collection := range b.Block.Payload.Guarantees { 112 113 completeCollection, ok := b.CompleteCollections[collection.ID()] 114 if ok && completeCollection.IsCompleted() { 115 continue 116 } 117 return false 118 } 119 return true 120 } 121 122 // HasStartState returns whether the block has StartState, which 123 // indicates whether its parent has been executed. 124 func (b *ExecutableBlock) HasStartState() bool { 125 return b.StartState != nil 126 } 127 128 // IsComplete returns whether all the data needed to executed the block are 129 // ready. 130 func (b *ExecutableBlock) IsComplete() bool { 131 return b.HasAllTransactions() && b.HasStartState() 132 }