github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/collection/epochmgr/factories/epoch.go (about)

     1  package factories
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/flow-go/consensus/hotstuff"
     7  	"github.com/onflow/flow-go/engine/collection/epochmgr"
     8  	"github.com/onflow/flow-go/module"
     9  	"github.com/onflow/flow-go/module/component"
    10  	"github.com/onflow/flow-go/module/mempool/epochs"
    11  	"github.com/onflow/flow-go/state/cluster"
    12  	"github.com/onflow/flow-go/state/cluster/badger"
    13  	"github.com/onflow/flow-go/state/protocol"
    14  	"github.com/onflow/flow-go/storage"
    15  )
    16  
    17  type EpochComponentsFactory struct {
    18  	me         module.Local
    19  	pools      *epochs.TransactionPools
    20  	builder    *BuilderFactory
    21  	state      *ClusterStateFactory
    22  	hotstuff   *HotStuffFactory
    23  	compliance *ComplianceEngineFactory
    24  	sync       *SyncEngineFactory
    25  	syncCore   *SyncCoreFactory
    26  	messageHub *MessageHubFactory
    27  }
    28  
    29  var _ epochmgr.EpochComponentsFactory = (*EpochComponentsFactory)(nil)
    30  
    31  func NewEpochComponentsFactory(
    32  	me module.Local,
    33  	pools *epochs.TransactionPools,
    34  	builder *BuilderFactory,
    35  	state *ClusterStateFactory,
    36  	hotstuff *HotStuffFactory,
    37  	compliance *ComplianceEngineFactory,
    38  	syncCore *SyncCoreFactory,
    39  	sync *SyncEngineFactory,
    40  	messageHub *MessageHubFactory,
    41  ) *EpochComponentsFactory {
    42  
    43  	factory := &EpochComponentsFactory{
    44  		me:         me,
    45  		pools:      pools,
    46  		builder:    builder,
    47  		state:      state,
    48  		hotstuff:   hotstuff,
    49  		compliance: compliance,
    50  		syncCore:   syncCore,
    51  		sync:       sync,
    52  		messageHub: messageHub,
    53  	}
    54  	return factory
    55  }
    56  
    57  func (factory *EpochComponentsFactory) Create(
    58  	epoch protocol.Epoch,
    59  ) (
    60  	state cluster.State,
    61  	compliance component.Component,
    62  	sync module.ReadyDoneAware,
    63  	hotstuff module.HotStuff,
    64  	voteAggregator hotstuff.VoteAggregator,
    65  	timeoutAggregator hotstuff.TimeoutAggregator,
    66  	messageHub component.Component,
    67  	err error,
    68  ) {
    69  
    70  	epochCounter, err := epoch.Counter()
    71  	if err != nil {
    72  		err = fmt.Errorf("could not get epoch counter: %w", err)
    73  		return
    74  	}
    75  
    76  	// if we are not an authorized participant in this epoch, return a sentinel
    77  	identities, err := epoch.InitialIdentities()
    78  	if err != nil {
    79  		err = fmt.Errorf("could not get initial identities for epoch: %w", err)
    80  		return
    81  	}
    82  	_, exists := identities.ByNodeID(factory.me.NodeID())
    83  	if !exists {
    84  		err = fmt.Errorf("%w (node_id=%x, epoch=%d)", epochmgr.ErrNotAuthorizedForEpoch, factory.me.NodeID(), epochCounter)
    85  		return
    86  	}
    87  
    88  	// determine this node's cluster for the epoch
    89  	clusters, err := epoch.Clustering()
    90  	if err != nil {
    91  		err = fmt.Errorf("could not get clusters for epoch: %w", err)
    92  		return
    93  	}
    94  	_, clusterIndex, ok := clusters.ByNodeID(factory.me.NodeID())
    95  	if !ok {
    96  		err = fmt.Errorf("could not find my cluster")
    97  		return
    98  	}
    99  	cluster, err := epoch.Cluster(clusterIndex)
   100  	if err != nil {
   101  		err = fmt.Errorf("could not get cluster info: %w", err)
   102  		return
   103  	}
   104  
   105  	// create the cluster state
   106  	var (
   107  		headers  storage.Headers
   108  		payloads storage.ClusterPayloads
   109  		blocks   storage.ClusterBlocks
   110  	)
   111  
   112  	stateRoot, err := badger.NewStateRoot(cluster.RootBlock(), cluster.RootQC(), cluster.EpochCounter())
   113  	if err != nil {
   114  		err = fmt.Errorf("could not create valid state root: %w", err)
   115  		return
   116  	}
   117  	var mutableState *badger.MutableState
   118  	mutableState, headers, payloads, blocks, err = factory.state.Create(stateRoot)
   119  	state = mutableState
   120  	if err != nil {
   121  		err = fmt.Errorf("could not create cluster state: %w", err)
   122  		return
   123  	}
   124  
   125  	// get the transaction pool for the epoch
   126  	pool := factory.pools.ForEpoch(epochCounter)
   127  
   128  	builder, finalizer, err := factory.builder.Create(state, headers, payloads, pool, epochCounter)
   129  	if err != nil {
   130  		err = fmt.Errorf("could not create builder/finalizer: %w", err)
   131  		return
   132  	}
   133  
   134  	hotstuffModules, metrics, err := factory.hotstuff.CreateModules(epoch, cluster, state, headers, payloads, finalizer)
   135  	if err != nil {
   136  		err = fmt.Errorf("could not create consensus modules: %w", err)
   137  		return
   138  	}
   139  	voteAggregator = hotstuffModules.VoteAggregator
   140  	timeoutAggregator = hotstuffModules.TimeoutAggregator
   141  	validator := hotstuffModules.Validator
   142  
   143  	hotstuff, err = factory.hotstuff.Create(
   144  		cluster,
   145  		state,
   146  		metrics,
   147  		builder,
   148  		headers,
   149  		hotstuffModules,
   150  	)
   151  	if err != nil {
   152  		err = fmt.Errorf("could not create hotstuff: %w", err)
   153  		return
   154  	}
   155  
   156  	syncCore, err := factory.syncCore.Create(cluster.ChainID())
   157  	if err != nil {
   158  		err = fmt.Errorf("could not create sync core: %w", err)
   159  		return
   160  	}
   161  
   162  	complianceEng, err := factory.compliance.Create(
   163  		metrics,
   164  		hotstuffModules.Notifier,
   165  		mutableState,
   166  		headers,
   167  		payloads,
   168  		syncCore,
   169  		hotstuff,
   170  		hotstuffModules.VoteAggregator,
   171  		hotstuffModules.TimeoutAggregator,
   172  		validator,
   173  	)
   174  	if err != nil {
   175  		err = fmt.Errorf("could not create compliance engine: %w", err)
   176  		return
   177  	}
   178  	compliance = complianceEng
   179  	hotstuffModules.Notifier.AddOnBlockFinalizedConsumer(complianceEng.OnFinalizedBlock)
   180  
   181  	sync, err = factory.sync.Create(cluster.Members(), state, blocks, syncCore, complianceEng)
   182  	if err != nil {
   183  		err = fmt.Errorf("could not create sync engine: %w", err)
   184  		return
   185  	}
   186  
   187  	clusterMessageHub, err := factory.messageHub.Create(state, payloads, hotstuff, complianceEng, hotstuffModules)
   188  	if err != nil {
   189  		err = fmt.Errorf("could not create message hub: %w", err)
   190  	}
   191  	hotstuffModules.Notifier.AddConsumer(clusterMessageHub)
   192  	messageHub = clusterMessageHub
   193  
   194  	return
   195  }