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

     1  package consensus
     2  
     3  import (
     4  	"github.com/rs/zerolog/log"
     5  
     6  	"github.com/koko1123/flow-go-1/model/flow"
     7  	"github.com/koko1123/flow-go-1/module/mempool"
     8  	"github.com/koko1123/flow-go-1/storage"
     9  	"github.com/koko1123/flow-go-1/utils/logging"
    10  )
    11  
    12  // IncorporatedResultSeals implements the incorporated result seals memory pool
    13  // of the consensus nodes.
    14  // ATTENTION: this is a temporary wrapper for `mempool.IncorporatedResultSeals`
    15  // to enforce that there are at least 2 receipts from _different_ ENs
    16  // committing to the same incorporated result.
    17  // This wrapper should only be used with `Core`.
    18  type IncorporatedResultSeals struct {
    19  	seals      mempool.IncorporatedResultSeals // seals mempool that wrapped
    20  	receiptsDB storage.ExecutionReceipts       // receipts DB to decide if we have multiple receipts for same result
    21  }
    22  
    23  // NewIncorporatedResultSeals creates a mempool for the incorporated result seals
    24  func NewIncorporatedResultSeals(mempool mempool.IncorporatedResultSeals, receiptsDB storage.ExecutionReceipts) *IncorporatedResultSeals {
    25  	return &IncorporatedResultSeals{
    26  		seals:      mempool,
    27  		receiptsDB: receiptsDB,
    28  	}
    29  }
    30  
    31  // Add adds an IncorporatedResultSeal to the mempool
    32  func (ir *IncorporatedResultSeals) Add(seal *flow.IncorporatedResultSeal) (bool, error) {
    33  	return ir.seals.Add(seal)
    34  }
    35  
    36  // All returns all the items in the mempool
    37  func (ir *IncorporatedResultSeals) All() []*flow.IncorporatedResultSeal {
    38  	unfiltered := ir.seals.All()
    39  	seals := make([]*flow.IncorporatedResultSeal, 0, len(unfiltered))
    40  	for _, s := range unfiltered {
    41  		if ir.resultHasMultipleReceipts(s.IncorporatedResult) {
    42  			seals = append(seals, s)
    43  		}
    44  	}
    45  	return seals
    46  }
    47  
    48  // resultHasMultipleReceipts implements an additional _temporary_ safety measure:
    49  // only consider incorporatedResult sealable if there are at AT LEAST 2 RECEIPTS
    50  // from _different_ ENs committing to the result.
    51  func (ir *IncorporatedResultSeals) resultHasMultipleReceipts(incorporatedResult *flow.IncorporatedResult) bool {
    52  	blockID := incorporatedResult.Result.BlockID // block that was computed
    53  	resultID := incorporatedResult.Result.ID()
    54  
    55  	// get all receipts that are known for the block
    56  	receipts, err := ir.receiptsDB.ByBlockID(blockID)
    57  	if err != nil {
    58  		log.Error().Err(err).
    59  			Hex("block_id", logging.ID(blockID)).
    60  			Msg("could not get receipts by block ID")
    61  		return false
    62  	}
    63  
    64  	// Index receipts for given incorporatedResult by their executor. In case
    65  	// there are multiple receipts from the same executor, we keep the last one.
    66  	receiptsForIncorporatedResults := receipts.GroupByResultID().GetGroup(resultID)
    67  	return receiptsForIncorporatedResults.GroupByExecutorID().NumberGroups() >= 2
    68  }
    69  
    70  // ByID gets an IncorporatedResultSeal by IncorporatedResult ID
    71  func (ir *IncorporatedResultSeals) ByID(id flow.Identifier) (*flow.IncorporatedResultSeal, bool) {
    72  	seal, ok := ir.seals.ByID(id)
    73  	if !ok {
    74  		return nil, false
    75  	}
    76  
    77  	// _temporary_ measure, return only receipts that have multiple commitments from different ENs.
    78  	if !ir.resultHasMultipleReceipts(seal.IncorporatedResult) {
    79  		return nil, false
    80  	}
    81  
    82  	return seal, true
    83  }
    84  
    85  // Limit returns the size limit of the mempool
    86  func (ir *IncorporatedResultSeals) Limit() uint {
    87  	return ir.seals.Limit()
    88  }
    89  
    90  // Remove removes an IncorporatedResultSeal from the mempool
    91  func (ir *IncorporatedResultSeals) Remove(id flow.Identifier) bool {
    92  	return ir.seals.Remove(id)
    93  }
    94  
    95  // Size returns the number of items in the mempool
    96  func (ir *IncorporatedResultSeals) Size() uint {
    97  	return ir.seals.Size()
    98  }
    99  
   100  // Clear removes all entities from the pool.
   101  func (ir *IncorporatedResultSeals) Clear() {
   102  	ir.seals.Clear()
   103  }
   104  
   105  // PruneUpToHeight remove all seals for blocks whose height is strictly
   106  // smaller that height. Note: seals for blocks at height are retained.
   107  func (ir *IncorporatedResultSeals) PruneUpToHeight(height uint64) error {
   108  	return ir.seals.PruneUpToHeight(height)
   109  }