@@ -243,9 +243,7 @@ func (m *VoteCollector) processVote(vote *model.Vote) error {
243243 // Informally, the state transition will happen _after_ we cached the vote.
244244 // * Case (c): `currentState` = [VoteCollectorStatusCaching] while `m.Status()` = [VoteCollectorStatusVerifying].
245245 // In this scenario, the vote is being fed into the [NoopProcessor] first, before we realize that the state has changed. However,
246- // since the status has changed, the check below will trigger a repeat of the processing, which will then enter case (a)
247- // (or leave the happy path by transitioning to [VoteCollectorStatusInvalid], implying we are dealing with a byzantine proposer, in which
248- // case we may drop all votes anyway).
246+ // since the status has changed, the check below will trigger a repeat of the processing, which will then enter case (a).
249247 // We have shown that all votes will reach the [VerifyingVoteProcessor] on the happy path.
250248 //
251249 // CAUTION: In the proof, we utilized that reading the `votesCache` happens before writing to it (case b). It is important to emphasize that
@@ -283,8 +281,6 @@ func (m *VoteCollector) View() uint64 {
283281// equal to `expectedValue`. The implementation only allows the transitions
284282//
285283// CachingVotes → VerifyingVotes
286- // CachingVotes → Invalid
287- // VerifyingVotes → Invalid
288284//
289285// No errors are expected during normal operation (Byzantine edge cases handled via notifications internally).
290286func (m * VoteCollector ) ProcessBlock (proposal * model.SignedProposal ) error {
@@ -339,13 +335,6 @@ func (m *VoteCollector) ProcessBlock(proposal *model.SignedProposal) error {
339335 return fmt .Errorf ("while processing block %v, found that VoteProcessor reports status %s but has an incompatible implementation type %T" ,
340336 proposal .Block .BlockID , proc .Status (), verifyingProc )
341337 }
342- if verifyingProc .Block ().BlockID != proposal .Block .BlockID {
343- m .terminateVoteProcessing ()
344- }
345-
346- // Vote processing for this view has already been terminated. Note: proposal equivocation
347- // is handled by hotstuff.Forks, so we don't have anything to do here.
348- case hotstuff .VoteCollectorStatusInvalid : /* no op */
349338
350339 default :
351340 return fmt .Errorf ("while processing block %v, found that VoteProcessor reported unknown status %s" , proposal .Block .BlockID , proc .Status ())
@@ -404,41 +393,6 @@ func (m *VoteCollector) caching2Verifying(proposal *model.SignedProposal) error
404393 return nil
405394}
406395
407- // terminateVoteProcessing atomically transitions the VoteCollector into state
408- // `VoteCollectorStatusInvalid`. if it wasn't already in this state.
409- func (m * VoteCollector ) terminateVoteProcessing () {
410- currentProcWrapper := m .votesProcessor .Load ().(* atomicValueWrapper )
411- if currentProcWrapper .processor .Status () == hotstuff .VoteCollectorStatusInvalid {
412- return
413- }
414-
415- newProcWrapper := & atomicValueWrapper {
416- processor : NewNoopCollector (hotstuff .VoteCollectorStatusInvalid ),
417- }
418-
419- // We now have an optimistically-constructed `newProcWrapper` that represents the desired new state (happy path). We must ensure
420- // that writing the `newProcWrapper` to `m.votesProcessor` happens ATOMICALLY if and only if the current state is not
421- // `VoteCollectorStatusInvalid`. The "Compare-And-Swap Loop" (CAS LOOP) is an efficient pattern to implement this:
422- // (i) We first retrieved the current state (above) and checked whether it is different from `VoteCollectorStatusInvalid`.
423- // (ii) If so, we attempt to compare-and-swap the current with the new state.
424- // Note that (i) and (ii) are separate operations. However, the CAS in (ii) ensures that the write only happens if the current state
425- // is still the same as what we observed in (i). If another thread changed the state in between (i) and (ii), we have worked with
426- // an outdated view of the current state, and should repeat the attempt to update the state (hence the "loop" in CAS LOOP).
427- // Since we are storing a pointer in the atomic.Value the value compared will be the reference to the object.
428- for {
429- stateUpdateSuccessful := m .votesProcessor .CompareAndSwap (currentProcWrapper , newProcWrapper )
430- if stateUpdateSuccessful {
431- return
432- }
433- // the `currentProcWrapper` we worked with was stale:
434- // reload, check if invalid target state has already been reached, and repeat if not
435- currentProcWrapper = m .votesProcessor .Load ().(* atomicValueWrapper )
436- if currentProcWrapper .processor .Status () == hotstuff .VoteCollectorStatusInvalid {
437- return
438- }
439- }
440- }
441-
442396// processCachedVotes feeds all cached votes into the VoteProcessor
443397func (m * VoteCollector ) processCachedVotes (block * model.Block ) {
444398 cachedVotes := m .votesCache .All ()
0 commit comments