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

     1  // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
     2  
     3  package mempool
     4  
     5  import (
     6  	"github.com/koko1123/flow-go-1/model/flow"
     7  )
     8  
     9  // ExecutionTree represents a concurrency-safe memory pool for execution
    10  // Receipts. Its is aware of the tree structure formed by execution results.
    11  // All execution receipts for the _same result_ form an equivalence class and
    12  // are represented by _one_ vertex in the execution tree. The mempool utilizes
    13  // knowledge about the height of the block the result is for. Hence, the
    14  // Mempool can only store and process Receipts whose block is known.
    15  //
    16  // Implementations are concurrency safe.
    17  type ExecutionTree interface {
    18  
    19  	// AddResult adds an Execution Result to the Execution Tree (without any receipts), in
    20  	// case the result is not already stored in the tree.
    21  	// This is useful for crash recovery:
    22  	// After recovering from a crash, the mempools are wiped and the sealed results will not
    23  	// be stored in the Execution Tree anymore. Adding the result to the tree allows to create
    24  	// a vertex in the tree without attaching any Execution Receipts to it.
    25  	AddResult(result *flow.ExecutionResult, block *flow.Header) error
    26  
    27  	// AddReceipt adds the given execution receipt to the memory pool. Requires height
    28  	// of the block the receipt is for. We enforce data consistency on an API
    29  	// level by using the block header as input.
    30  	AddReceipt(receipt *flow.ExecutionReceipt, block *flow.Header) (bool, error)
    31  
    32  	// HasReceipt returns true if the given receipt is already present in the mempool.
    33  	HasReceipt(receipt *flow.ExecutionReceipt) bool
    34  
    35  	// ReachableReceipts returns a slice of ExecutionReceipt, whose result
    36  	// is computationally reachable from resultID. Context:
    37  	// * Conceptually, the Execution results form a tree, which we refer to as
    38  	//   Execution Tree. A branch in the execution can be due to a fork in the main
    39  	//   chain. Furthermore, the execution branches if ENs disagree about the result
    40  	//   for the same block.
    41  	// * As the ID of an execution result contains the BlockID, which the result
    42  	//   for, all Execution Results with the same ID necessarily are for the same
    43  	//   block. All Execution Receipts committing to the same result from an
    44  	//   equivalence class and can be represented as one vertex in the Execution
    45  	//   Tree.
    46  	// * An execution result r1 points (field ExecutionResult.ParentResultID) to
    47  	//   its parent result r0 , whose end state was used as the starting state
    48  	//   to compute r1. Formally, we have an edge r0 -> r1 in the Execution Tree,
    49  	//   if a result r1 is stored in the mempool, whose ParentResultID points to
    50  	//   r0.
    51  	// ReachableReceipts implements a tree search on the Execution Tree starting
    52  	// from the provided resultID. Execution Receipts are traversed in a
    53  	// parent-first manner, meaning that a the parent result is traversed
    54  	// _before_ any of its derived results. The algorithm only traverses to
    55  	// results, for which there exists a sequence of interim result in the
    56  	// mempool without any gaps.
    57  	//
    58  	// Two filters are supplied:
    59  	// * blockFilter: the tree search will only travers to results for
    60  	//   blocks which pass the filter. Often higher-level logic is only
    61  	//   interested in results for blocks in a specific fork. Such can be
    62  	//   implemented by a suitable blockFilter.
    63  	// * receiptFilter: for a reachable result (subject to the restrictions
    64  	//   imposed by blockFilter, all known receipts are returned.
    65  	//   While _all_ Receipts for the parent result are guaranteed to be
    66  	//   listed before the receipts for the derived results, there is no
    67  	//   specific ordering for the receipts committing to the same result
    68  	//   (random order). If only a subset of receipts for a result is desired
    69  	//   (e.g. for de-duplication with parent blocks), receiptFilter should
    70  	//   be used.
    71  	// Note the important difference between the two filters:
    72  	// * The blockFilter suppresses traversal to derived results.
    73  	// * The receiptFilter does _not_ suppresses traversal to derived results.
    74  	//   Only individual receipts are dropped.
    75  	//
    76  	// Error returns:
    77  	// * UnknownExecutionResultError (sentinel) if resultID is unknown
    78  	// * all other error are unexpected and potential indicators of corrupted internal state
    79  	ReachableReceipts(resultID flow.Identifier, blockFilter BlockFilter, receiptFilter ReceiptFilter) ([]*flow.ExecutionReceipt, error)
    80  
    81  	// Size returns the number of receipts stored in the mempool
    82  	Size() uint
    83  
    84  	// PruneUpToHeight prunes all results for all blocks with height up to but
    85  	// NOT INCLUDING `newLowestHeight`. Errors if newLowestHeight is smaller than
    86  	// the previous value (as we cannot recover previously pruned results).
    87  	PruneUpToHeight(newLowestHeight uint64) error
    88  
    89  	// LowestHeight returns the lowest height, where results are still
    90  	// stored in the mempool.
    91  	LowestHeight() uint64
    92  }
    93  
    94  // BlockFilter is used for controlling the ExecutionTree's Execution Tree search.
    95  // The search only traverses to results for blocks which pass the filter.
    96  // If an the block for an execution result does not pass the filter, the entire
    97  // sub-tree of derived results is not traversed.
    98  type BlockFilter func(header *flow.Header) bool
    99  
   100  // ReceiptFilter is used to drop specific receipts from. It does NOT
   101  // affect the ExecutionTree's Execution Tree search.
   102  type ReceiptFilter func(receipt *flow.ExecutionReceipt) bool