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 }