github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/notifications/pubsub/finalization_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  )
     9  
    10  type OnBlockFinalizedConsumer = func(block *model.Block)
    11  type OnBlockIncorporatedConsumer = func(block *model.Block)
    12  
    13  // FinalizationDistributor ingests events from HotStuff's logic for tracking forks + finalization
    14  // and distributes them to consumers. This logic generally runs inside all nodes (irrespectively whether
    15  // they are active consensus participants or or only consensus followers).
    16  // Concurrently safe.
    17  type FinalizationDistributor struct {
    18  	blockFinalizedConsumers    []OnBlockFinalizedConsumer
    19  	blockIncorporatedConsumers []OnBlockIncorporatedConsumer
    20  	consumers                  []hotstuff.FinalizationConsumer
    21  	lock                       sync.RWMutex
    22  }
    23  
    24  var _ hotstuff.FinalizationConsumer = (*FinalizationDistributor)(nil)
    25  
    26  func NewFinalizationDistributor() *FinalizationDistributor {
    27  	return &FinalizationDistributor{}
    28  }
    29  
    30  func (d *FinalizationDistributor) AddOnBlockFinalizedConsumer(consumer OnBlockFinalizedConsumer) {
    31  	d.lock.Lock()
    32  	defer d.lock.Unlock()
    33  	d.blockFinalizedConsumers = append(d.blockFinalizedConsumers, consumer)
    34  }
    35  
    36  func (d *FinalizationDistributor) AddOnBlockIncorporatedConsumer(consumer OnBlockIncorporatedConsumer) {
    37  	d.lock.Lock()
    38  	defer d.lock.Unlock()
    39  	d.blockIncorporatedConsumers = append(d.blockIncorporatedConsumers, consumer)
    40  }
    41  
    42  func (d *FinalizationDistributor) AddFinalizationConsumer(consumer hotstuff.FinalizationConsumer) {
    43  	d.lock.Lock()
    44  	defer d.lock.Unlock()
    45  	d.consumers = append(d.consumers, consumer)
    46  }
    47  
    48  func (d *FinalizationDistributor) OnBlockIncorporated(block *model.Block) {
    49  	d.lock.RLock()
    50  	defer d.lock.RUnlock()
    51  	for _, consumer := range d.blockIncorporatedConsumers {
    52  		consumer(block)
    53  	}
    54  	for _, consumer := range d.consumers {
    55  		consumer.OnBlockIncorporated(block)
    56  	}
    57  }
    58  
    59  func (d *FinalizationDistributor) OnFinalizedBlock(block *model.Block) {
    60  	d.lock.RLock()
    61  	defer d.lock.RUnlock()
    62  	for _, consumer := range d.blockFinalizedConsumers {
    63  		consumer(block)
    64  	}
    65  	for _, consumer := range d.consumers {
    66  		consumer.OnFinalizedBlock(block)
    67  	}
    68  }