github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/consensus/approvals/caching_assignment_collector.go (about) 1 package approvals 2 3 import ( 4 "fmt" 5 6 "github.com/rs/zerolog" 7 8 "github.com/onflow/flow-go/engine" 9 "github.com/onflow/flow-go/engine/consensus" 10 "github.com/onflow/flow-go/model/flow" 11 ) 12 13 // CachingAssignmentCollector is an AssignmentCollectorState with the fixed `ProcessingStatus` of `CachingApprovals`. 14 type CachingAssignmentCollector struct { 15 AssignmentCollectorBase 16 17 log zerolog.Logger 18 approvalsCache *ApprovalsCache // in-memory cache of approvals (not-verified) 19 incResCache *IncorporatedResultsCache // in-memory cache for incorporated results that were processed 20 } 21 22 func NewCachingAssignmentCollector(collectorBase AssignmentCollectorBase) *CachingAssignmentCollector { 23 return &CachingAssignmentCollector{ 24 AssignmentCollectorBase: collectorBase, 25 log: collectorBase.log.With().Str("component", "caching_assignment_collector").Logger(), 26 approvalsCache: NewApprovalsCache(0), 27 incResCache: NewIncorporatedResultsCache(0), 28 } 29 } 30 31 func (ac *CachingAssignmentCollector) ProcessingStatus() ProcessingStatus { return CachingApprovals } 32 func (ac *CachingAssignmentCollector) CheckEmergencySealing(consensus.SealingObservation, uint64) error { 33 return nil 34 } 35 func (ac *CachingAssignmentCollector) RequestMissingApprovals(consensus.SealingObservation, uint64) (uint, error) { 36 return 0, nil 37 } 38 39 // ProcessIncorporatedResult starts tracking the approval for IncorporatedResult. 40 // Method is idempotent. 41 // Error Returns: 42 // - no errors expected during normal operation; 43 // errors might be symptoms of bugs or internal state corruption (fatal) 44 func (ac *CachingAssignmentCollector) ProcessIncorporatedResult(incorporatedResult *flow.IncorporatedResult) error { 45 // check that result is the one that this VerifyingAssignmentCollector manages 46 if resID := incorporatedResult.Result.ID(); resID != ac.ResultID() { 47 return fmt.Errorf("this VerifyingAssignmentCollector manages result %x but got %x", ac.ResultID(), resID) 48 } 49 50 // In case the result is already cached, we first read the cache. 51 // This is much cheaper than attempting to write right away. 52 irID := incorporatedResult.ID() 53 if cached := ac.incResCache.Get(irID); cached != nil { 54 return nil 55 } 56 ac.incResCache.Put(irID, incorporatedResult) 57 return nil 58 } 59 60 // ProcessApproval ingests Result Approvals and triggers sealing of execution result 61 // when sufficient approvals have arrived. 62 // Error Returns: 63 // - nil in case of success (outdated approvals might be silently discarded) 64 // - engine.InvalidInputError if the result approval is invalid 65 // - any other errors might be symptoms of bugs or internal state corruption (fatal) 66 func (ac *CachingAssignmentCollector) ProcessApproval(approval *flow.ResultApproval) error { 67 ac.log.Debug(). 68 Str("result_id", approval.Body.ExecutionResultID.String()). 69 Str("verifier_id", approval.Body.ApproverID.String()). 70 Msg("processing result approval") 71 72 // check that approval is for the expected result to reject incompatible inputs 73 if approval.Body.ExecutionResultID != ac.ResultID() { 74 return fmt.Errorf("this CachingAssignmentCollector processes only approvals for result (%x) but got an approval for (%x)", ac.resultID, approval.Body.ExecutionResultID) 75 } 76 // approval has to refer same block as execution result 77 if approval.Body.BlockID != ac.BlockID() { 78 return engine.NewInvalidInputErrorf("result approval for invalid block, expected (%x) vs (%x)", 79 ac.BlockID(), approval.Body.BlockID) 80 } 81 82 // if we have this approval cached already, no need to process it again 83 approvalCacheID := approval.Body.PartialID() 84 if cached := ac.approvalsCache.Get(approvalCacheID); cached != nil { 85 return nil 86 } 87 ac.approvalsCache.Put(approvalCacheID, approval) 88 return nil 89 } 90 91 func (ac *CachingAssignmentCollector) GetIncorporatedResults() []*flow.IncorporatedResult { 92 return ac.incResCache.All() 93 } 94 95 func (ac *CachingAssignmentCollector) GetApprovals() []*flow.ResultApproval { 96 return ac.approvalsCache.All() 97 }