github.com/koko1123/flow-go-1@v0.29.6/engine/collection/epochmgr/factories/hotstuff.go (about)

     1  package factories
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dgraph-io/badger/v3"
     7  	"github.com/rs/zerolog"
     8  
     9  	"github.com/koko1123/flow-go-1/consensus"
    10  	"github.com/koko1123/flow-go-1/consensus/hotstuff"
    11  	"github.com/koko1123/flow-go-1/consensus/hotstuff/blockproducer"
    12  	"github.com/koko1123/flow-go-1/consensus/hotstuff/committees"
    13  	"github.com/koko1123/flow-go-1/consensus/hotstuff/notifications"
    14  	"github.com/koko1123/flow-go-1/consensus/hotstuff/notifications/pubsub"
    15  	"github.com/koko1123/flow-go-1/consensus/hotstuff/persister"
    16  	validatorImpl "github.com/koko1123/flow-go-1/consensus/hotstuff/validator"
    17  	"github.com/koko1123/flow-go-1/consensus/hotstuff/verification"
    18  	"github.com/koko1123/flow-go-1/consensus/hotstuff/votecollector"
    19  	recovery "github.com/koko1123/flow-go-1/consensus/recovery/cluster"
    20  	"github.com/koko1123/flow-go-1/model/flow"
    21  	"github.com/koko1123/flow-go-1/module"
    22  	hotmetrics "github.com/koko1123/flow-go-1/module/metrics/hotstuff"
    23  	"github.com/koko1123/flow-go-1/state/cluster"
    24  	"github.com/koko1123/flow-go-1/state/protocol"
    25  	"github.com/koko1123/flow-go-1/storage"
    26  )
    27  
    28  type HotStuffMetricsFunc func(chainID flow.ChainID) module.HotstuffMetrics
    29  
    30  type HotStuffFactory struct {
    31  	log           zerolog.Logger
    32  	me            module.Local
    33  	db            *badger.DB
    34  	protoState    protocol.State
    35  	createMetrics HotStuffMetricsFunc
    36  	opts          []consensus.Option
    37  }
    38  
    39  func NewHotStuffFactory(
    40  	log zerolog.Logger,
    41  	me module.Local,
    42  	db *badger.DB,
    43  	protoState protocol.State,
    44  	createMetrics HotStuffMetricsFunc,
    45  	opts ...consensus.Option,
    46  ) (*HotStuffFactory, error) {
    47  
    48  	factory := &HotStuffFactory{
    49  		log:           log,
    50  		me:            me,
    51  		db:            db,
    52  		protoState:    protoState,
    53  		createMetrics: createMetrics,
    54  		opts:          opts,
    55  	}
    56  	return factory, nil
    57  }
    58  
    59  func (f *HotStuffFactory) CreateModules(
    60  	epoch protocol.Epoch,
    61  	cluster protocol.Cluster,
    62  	clusterState cluster.State,
    63  	headers storage.Headers,
    64  	payloads storage.ClusterPayloads,
    65  	updater module.Finalizer,
    66  ) (*consensus.HotstuffModules, module.HotstuffMetrics, error) {
    67  
    68  	// setup metrics/logging with the new chain ID
    69  	metrics := f.createMetrics(cluster.ChainID())
    70  	notifier := pubsub.NewDistributor()
    71  	finalizationDistributor := pubsub.NewFinalizationDistributor()
    72  	notifier.AddConsumer(finalizationDistributor)
    73  	notifier.AddConsumer(notifications.NewLogConsumer(f.log))
    74  	notifier.AddConsumer(hotmetrics.NewMetricsConsumer(metrics))
    75  	notifier.AddConsumer(notifications.NewTelemetryConsumer(f.log, cluster.ChainID()))
    76  
    77  	var (
    78  		err       error
    79  		committee hotstuff.Committee
    80  	)
    81  	committee, err = committees.NewClusterCommittee(f.protoState, payloads, cluster, epoch, f.me.NodeID())
    82  	if err != nil {
    83  		return nil, nil, fmt.Errorf("could not create cluster committee: %w", err)
    84  	}
    85  	committee = committees.NewMetricsWrapper(committee, metrics) // wrapper for measuring time spent determining consensus committee relations
    86  
    87  	// create a signing provider
    88  	var signer hotstuff.Signer = verification.NewStakingSigner(f.me)
    89  	signer = verification.NewMetricsWrapper(signer, metrics) // wrapper for measuring time spent with crypto-related operations
    90  
    91  	finalizedBlock, err := clusterState.Final().Head()
    92  	if err != nil {
    93  		return nil, nil, fmt.Errorf("could not get cluster finalized block: %w", err)
    94  	}
    95  
    96  	forks, err := consensus.NewForks(
    97  		finalizedBlock,
    98  		headers,
    99  		updater,
   100  		notifier,
   101  		cluster.RootBlock().Header,
   102  		cluster.RootQC(),
   103  	)
   104  	if err != nil {
   105  		return nil, nil, err
   106  	}
   107  
   108  	qcDistributor := pubsub.NewQCCreatedDistributor()
   109  
   110  	verifier := verification.NewStakingVerifier()
   111  	validator := validatorImpl.NewMetricsWrapper(validatorImpl.New(committee, forks, verifier), metrics)
   112  	voteProcessorFactory := votecollector.NewStakingVoteProcessorFactory(committee, qcDistributor.OnQcConstructedFromVotes)
   113  	aggregator, err := consensus.NewVoteAggregator(
   114  		f.log,
   115  		// since we don't want to aggregate votes for finalized view,
   116  		// the lowest retained view starts with the next view of the last finalized view.
   117  		finalizedBlock.View+1,
   118  		notifier,
   119  		voteProcessorFactory,
   120  		finalizationDistributor,
   121  	)
   122  	if err != nil {
   123  		return nil, nil, err
   124  	}
   125  
   126  	return &consensus.HotstuffModules{
   127  		Forks:                   forks,
   128  		Validator:               validator,
   129  		Notifier:                notifier,
   130  		Committee:               committee,
   131  		Signer:                  signer,
   132  		Persist:                 persister.New(f.db, cluster.ChainID()),
   133  		Aggregator:              aggregator,
   134  		QCCreatedDistributor:    qcDistributor,
   135  		FinalizationDistributor: finalizationDistributor,
   136  	}, metrics, nil
   137  }
   138  
   139  func (f *HotStuffFactory) Create(
   140  	clusterState cluster.State,
   141  	metrics module.HotstuffMetrics,
   142  	builder module.Builder,
   143  	headers storage.Headers,
   144  	communicator hotstuff.Communicator,
   145  	hotstuffModules *consensus.HotstuffModules,
   146  ) (module.HotStuff, error) {
   147  
   148  	// setup metrics/logging with the new chain ID
   149  	builder = blockproducer.NewMetricsWrapper(builder, metrics) // wrapper for measuring time spent building block payload component
   150  
   151  	finalizedBlock, pendingBlocks, err := recovery.FindLatest(clusterState, headers)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	participant, err := consensus.NewParticipant(
   157  		f.log,
   158  		metrics,
   159  		builder,
   160  		communicator,
   161  		finalizedBlock,
   162  		pendingBlocks,
   163  		hotstuffModules,
   164  		f.opts...,
   165  	)
   166  	return participant, err
   167  }