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 }