github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/consensus/approvals/chunk_collector.go (about)

     1  package approvals
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/onflow/flow-go/model/flow"
     7  )
     8  
     9  // ChunkApprovalCollector implements logic for checking chunks against assignments as
    10  // well as accumulating signatures of already checked approvals.
    11  type ChunkApprovalCollector struct {
    12  	assignment                           map[flow.Identifier]struct{} // set of verifiers that were assigned to current chunk
    13  	chunkApprovals                       SignatureCollector           // accumulator of signatures for current collector
    14  	lock                                 sync.Mutex                   // lock to protect `chunkApprovals`
    15  	requiredApprovalsForSealConstruction uint                         // number of approvals that are required for each chunk to be sealed
    16  }
    17  
    18  func NewChunkApprovalCollector(assignment map[flow.Identifier]struct{}, requiredApprovalsForSealConstruction uint) *ChunkApprovalCollector {
    19  	return &ChunkApprovalCollector{
    20  		assignment:                           assignment,
    21  		chunkApprovals:                       NewSignatureCollector(),
    22  		lock:                                 sync.Mutex{},
    23  		requiredApprovalsForSealConstruction: requiredApprovalsForSealConstruction,
    24  	}
    25  }
    26  
    27  // ProcessApproval performs processing and bookkeeping of single approval
    28  func (c *ChunkApprovalCollector) ProcessApproval(approval *flow.ResultApproval) (flow.AggregatedSignature, bool) {
    29  	approverID := approval.Body.ApproverID
    30  	if _, ok := c.assignment[approverID]; ok {
    31  		c.lock.Lock()
    32  		defer c.lock.Unlock()
    33  		c.chunkApprovals.Add(approverID, approval.Body.AttestationSignature)
    34  		if c.chunkApprovals.NumberSignatures() >= c.requiredApprovalsForSealConstruction {
    35  			return c.chunkApprovals.ToAggregatedSignature(), true
    36  		}
    37  	}
    38  
    39  	return flow.AggregatedSignature{}, false
    40  }
    41  
    42  // GetMissingSigners returns ids of approvers that are present in assignment but didn't provide approvals
    43  func (c *ChunkApprovalCollector) GetMissingSigners() flow.IdentifierList {
    44  	// provide capacity for worst-case
    45  	result := make(flow.IdentifierList, 0, len(c.assignment))
    46  	c.lock.Lock()
    47  	for id := range c.assignment {
    48  		if hasSigned := c.chunkApprovals.HasSigned(id); !hasSigned {
    49  			result = append(result, id)
    50  		}
    51  	}
    52  	c.lock.Unlock()
    53  
    54  	return result
    55  }