github.com/koko1123/flow-go-1@v0.29.6/module/mempool/entity/executableblock.go (about)

     1  package entity
     2  
     3  import (
     4  	"github.com/koko1123/flow-go-1/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  // HasAllTransactions returns whether all the transactions for all collections
    90  // in the block have been received.
    91  func (b *ExecutableBlock) HasAllTransactions() bool {
    92  	for _, collection := range b.Block.Payload.Guarantees {
    93  
    94  		completeCollection, ok := b.CompleteCollections[collection.ID()]
    95  		if ok && completeCollection.IsCompleted() {
    96  			continue
    97  		}
    98  		return false
    99  	}
   100  	return true
   101  }
   102  
   103  // HasStartState returns whether the block has StartState, which
   104  // indicates whether its parent has been executed.
   105  func (b *ExecutableBlock) HasStartState() bool {
   106  	return b.StartState != nil
   107  }
   108  
   109  // IsComplete returns whether all the data needed to executed the block are
   110  // ready.
   111  func (b *ExecutableBlock) IsComplete() bool {
   112  	return b.HasAllTransactions() && b.HasStartState()
   113  }