github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/notifications/pubsub/participant_distributor.go (about)

     1  package pubsub
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/onflow/flow-go/consensus/hotstuff"
     7  	"github.com/onflow/flow-go/consensus/hotstuff/model"
     8  	"github.com/onflow/flow-go/model/flow"
     9  )
    10  
    11  // ParticipantDistributor ingests events from HotStuff's core logic and distributes them to
    12  // consumers. This logic only runs inside active consensus participants proposing blocks, voting,
    13  // collecting + aggregating votes to QCs, and participating in the pacemaker (sending timeouts,
    14  // collecting + aggregating timeouts to TCs).
    15  // Concurrently safe.
    16  type ParticipantDistributor struct {
    17  	consumers []hotstuff.ParticipantConsumer
    18  	lock      sync.RWMutex
    19  }
    20  
    21  var _ hotstuff.ParticipantConsumer = (*ParticipantDistributor)(nil)
    22  
    23  func NewParticipantDistributor() *ParticipantDistributor {
    24  	return &ParticipantDistributor{}
    25  }
    26  
    27  func (d *ParticipantDistributor) AddParticipantConsumer(consumer hotstuff.ParticipantConsumer) {
    28  	d.lock.Lock()
    29  	defer d.lock.Unlock()
    30  	d.consumers = append(d.consumers, consumer)
    31  }
    32  
    33  func (d *ParticipantDistributor) OnEventProcessed() {
    34  	d.lock.RLock()
    35  	defer d.lock.RUnlock()
    36  	for _, subscriber := range d.consumers {
    37  		subscriber.OnEventProcessed()
    38  	}
    39  }
    40  
    41  func (d *ParticipantDistributor) OnStart(currentView uint64) {
    42  	d.lock.RLock()
    43  	defer d.lock.RUnlock()
    44  	for _, subscriber := range d.consumers {
    45  		subscriber.OnStart(currentView)
    46  	}
    47  }
    48  
    49  func (d *ParticipantDistributor) OnReceiveProposal(currentView uint64, proposal *model.Proposal) {
    50  	d.lock.RLock()
    51  	defer d.lock.RUnlock()
    52  	for _, subscriber := range d.consumers {
    53  		subscriber.OnReceiveProposal(currentView, proposal)
    54  	}
    55  }
    56  
    57  func (d *ParticipantDistributor) OnReceiveQc(currentView uint64, qc *flow.QuorumCertificate) {
    58  	d.lock.RLock()
    59  	defer d.lock.RUnlock()
    60  	for _, subscriber := range d.consumers {
    61  		subscriber.OnReceiveQc(currentView, qc)
    62  	}
    63  }
    64  
    65  func (d *ParticipantDistributor) OnReceiveTc(currentView uint64, tc *flow.TimeoutCertificate) {
    66  	d.lock.RLock()
    67  	defer d.lock.RUnlock()
    68  	for _, subscriber := range d.consumers {
    69  		subscriber.OnReceiveTc(currentView, tc)
    70  	}
    71  }
    72  
    73  func (d *ParticipantDistributor) OnPartialTc(currentView uint64, partialTc *hotstuff.PartialTcCreated) {
    74  	d.lock.RLock()
    75  	defer d.lock.RUnlock()
    76  	for _, subscriber := range d.consumers {
    77  		subscriber.OnPartialTc(currentView, partialTc)
    78  	}
    79  }
    80  
    81  func (d *ParticipantDistributor) OnLocalTimeout(currentView uint64) {
    82  	d.lock.RLock()
    83  	defer d.lock.RUnlock()
    84  	for _, subscriber := range d.consumers {
    85  		subscriber.OnLocalTimeout(currentView)
    86  	}
    87  }
    88  
    89  func (d *ParticipantDistributor) OnViewChange(oldView, newView uint64) {
    90  	d.lock.RLock()
    91  	defer d.lock.RUnlock()
    92  	for _, subscriber := range d.consumers {
    93  		subscriber.OnViewChange(oldView, newView)
    94  	}
    95  }
    96  
    97  func (d *ParticipantDistributor) OnQcTriggeredViewChange(oldView uint64, newView uint64, qc *flow.QuorumCertificate) {
    98  	d.lock.RLock()
    99  	defer d.lock.RUnlock()
   100  	for _, subscriber := range d.consumers {
   101  		subscriber.OnQcTriggeredViewChange(oldView, newView, qc)
   102  	}
   103  }
   104  
   105  func (d *ParticipantDistributor) OnTcTriggeredViewChange(oldView uint64, newView uint64, tc *flow.TimeoutCertificate) {
   106  	d.lock.RLock()
   107  	defer d.lock.RUnlock()
   108  	for _, subscriber := range d.consumers {
   109  		subscriber.OnTcTriggeredViewChange(oldView, newView, tc)
   110  	}
   111  }
   112  
   113  func (d *ParticipantDistributor) OnStartingTimeout(timerInfo model.TimerInfo) {
   114  	d.lock.RLock()
   115  	defer d.lock.RUnlock()
   116  	for _, subscriber := range d.consumers {
   117  		subscriber.OnStartingTimeout(timerInfo)
   118  	}
   119  }
   120  
   121  func (d *ParticipantDistributor) OnCurrentViewDetails(currentView, finalizedView uint64, currentLeader flow.Identifier) {
   122  	d.lock.RLock()
   123  	defer d.lock.RUnlock()
   124  	for _, subscriber := range d.consumers {
   125  		subscriber.OnCurrentViewDetails(currentView, finalizedView, currentLeader)
   126  	}
   127  }