github.com/onflow/flow-go@v0.33.17/state/protocol/inmem/epoch.go (about) 1 package inmem 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/flow-go/model/encodable" 7 "github.com/onflow/flow-go/model/flow" 8 "github.com/onflow/flow-go/model/flow/factory" 9 "github.com/onflow/flow-go/model/flow/filter" 10 "github.com/onflow/flow-go/module/signature" 11 "github.com/onflow/flow-go/state/cluster" 12 "github.com/onflow/flow-go/state/protocol" 13 "github.com/onflow/flow-go/state/protocol/invalid" 14 ) 15 16 // Epoch is a memory-backed implementation of protocol.Epoch. 17 type Epoch struct { 18 enc EncodableEpoch 19 } 20 21 var _ protocol.Epoch = (*Epoch)(nil) 22 23 func (e Epoch) Encodable() EncodableEpoch { 24 return e.enc 25 } 26 27 func (e Epoch) Counter() (uint64, error) { return e.enc.Counter, nil } 28 func (e Epoch) FirstView() (uint64, error) { return e.enc.FirstView, nil } 29 func (e Epoch) DKGPhase1FinalView() (uint64, error) { return e.enc.DKGPhase1FinalView, nil } 30 func (e Epoch) DKGPhase2FinalView() (uint64, error) { return e.enc.DKGPhase2FinalView, nil } 31 func (e Epoch) DKGPhase3FinalView() (uint64, error) { return e.enc.DKGPhase3FinalView, nil } 32 func (e Epoch) FinalView() (uint64, error) { return e.enc.FinalView, nil } 33 func (e Epoch) InitialIdentities() (flow.IdentityList, error) { 34 return e.enc.InitialIdentities, nil 35 } 36 func (e Epoch) RandomSource() ([]byte, error) { 37 return e.enc.RandomSource, nil 38 } 39 40 func (e Epoch) Clustering() (flow.ClusterList, error) { 41 return e.enc.Clustering, nil 42 } 43 44 func (e Epoch) DKG() (protocol.DKG, error) { 45 if e.enc.DKG != nil { 46 return DKG{*e.enc.DKG}, nil 47 } 48 return nil, protocol.ErrNextEpochNotCommitted 49 } 50 51 func (e Epoch) Cluster(i uint) (protocol.Cluster, error) { 52 if e.enc.Clusters == nil { 53 return nil, protocol.ErrNextEpochNotCommitted 54 } 55 56 if i >= uint(len(e.enc.Clusters)) { 57 return nil, fmt.Errorf("no cluster with index %d: %w", i, protocol.ErrClusterNotFound) 58 } 59 return Cluster{e.enc.Clusters[i]}, nil 60 } 61 62 func (e Epoch) ClusterByChainID(chainID flow.ChainID) (protocol.Cluster, error) { 63 if e.enc.Clusters == nil { 64 return nil, protocol.ErrNextEpochNotCommitted 65 } 66 67 for _, cluster := range e.enc.Clusters { 68 if cluster.RootBlock.Header.ChainID == chainID { 69 return Cluster{cluster}, nil 70 } 71 } 72 chainIDs := make([]string, 0, len(e.enc.Clusters)) 73 for _, cluster := range e.enc.Clusters { 74 chainIDs = append(chainIDs, string(cluster.RootBlock.Header.ChainID)) 75 } 76 return nil, fmt.Errorf("no cluster with the given chain ID %v, available chainIDs %v: %w", chainID, chainIDs, protocol.ErrClusterNotFound) 77 } 78 79 func (e Epoch) FinalHeight() (uint64, error) { 80 if e.enc.FinalHeight != nil { 81 return *e.enc.FinalHeight, nil 82 } 83 return 0, protocol.ErrEpochTransitionNotFinalized 84 } 85 86 func (e Epoch) FirstHeight() (uint64, error) { 87 if e.enc.FirstHeight != nil { 88 return *e.enc.FirstHeight, nil 89 } 90 return 0, protocol.ErrEpochTransitionNotFinalized 91 } 92 93 type Epochs struct { 94 enc EncodableEpochs 95 } 96 97 var _ protocol.EpochQuery = (*Epochs)(nil) 98 99 func (eq Epochs) Previous() protocol.Epoch { 100 if eq.enc.Previous != nil { 101 return Epoch{*eq.enc.Previous} 102 } 103 return invalid.NewEpoch(protocol.ErrNoPreviousEpoch) 104 } 105 func (eq Epochs) Current() protocol.Epoch { 106 return Epoch{eq.enc.Current} 107 } 108 func (eq Epochs) Next() protocol.Epoch { 109 if eq.enc.Next != nil { 110 return Epoch{*eq.enc.Next} 111 } 112 return invalid.NewEpoch(protocol.ErrNextEpochNotSetup) 113 } 114 115 // setupEpoch is an implementation of protocol.Epoch backed by an EpochSetup 116 // service event. This is used for converting service events to inmem.Epoch. 117 type setupEpoch struct { 118 // EpochSetup service event 119 setupEvent *flow.EpochSetup 120 } 121 122 func (es *setupEpoch) Counter() (uint64, error) { 123 return es.setupEvent.Counter, nil 124 } 125 126 func (es *setupEpoch) FirstView() (uint64, error) { 127 return es.setupEvent.FirstView, nil 128 } 129 130 func (es *setupEpoch) DKGPhase1FinalView() (uint64, error) { 131 return es.setupEvent.DKGPhase1FinalView, nil 132 } 133 134 func (es *setupEpoch) DKGPhase2FinalView() (uint64, error) { 135 return es.setupEvent.DKGPhase2FinalView, nil 136 } 137 138 func (es *setupEpoch) DKGPhase3FinalView() (uint64, error) { 139 return es.setupEvent.DKGPhase3FinalView, nil 140 } 141 142 func (es *setupEpoch) FinalView() (uint64, error) { 143 return es.setupEvent.FinalView, nil 144 } 145 146 func (es *setupEpoch) RandomSource() ([]byte, error) { 147 return es.setupEvent.RandomSource, nil 148 } 149 150 func (es *setupEpoch) InitialIdentities() (flow.IdentityList, error) { 151 identities := es.setupEvent.Participants.Filter(filter.Any) 152 return identities, nil 153 } 154 155 func (es *setupEpoch) Clustering() (flow.ClusterList, error) { 156 return ClusteringFromSetupEvent(es.setupEvent) 157 } 158 159 func ClusteringFromSetupEvent(setupEvent *flow.EpochSetup) (flow.ClusterList, error) { 160 collectorFilter := filter.HasRole(flow.RoleCollection) 161 clustering, err := factory.NewClusterList(setupEvent.Assignments, setupEvent.Participants.Filter(collectorFilter)) 162 if err != nil { 163 return nil, fmt.Errorf("failed to generate ClusterList from collector identities: %w", err) 164 } 165 return clustering, nil 166 } 167 168 func (es *setupEpoch) Cluster(_ uint) (protocol.Cluster, error) { 169 return nil, protocol.ErrNextEpochNotCommitted 170 } 171 172 func (es *setupEpoch) ClusterByChainID(_ flow.ChainID) (protocol.Cluster, error) { 173 return nil, protocol.ErrNextEpochNotCommitted 174 } 175 176 func (es *setupEpoch) DKG() (protocol.DKG, error) { 177 return nil, protocol.ErrNextEpochNotCommitted 178 } 179 180 func (es *setupEpoch) FirstHeight() (uint64, error) { 181 return 0, protocol.ErrEpochTransitionNotFinalized 182 } 183 184 func (es *setupEpoch) FinalHeight() (uint64, error) { 185 return 0, protocol.ErrEpochTransitionNotFinalized 186 } 187 188 // committedEpoch is an implementation of protocol.Epoch backed by an EpochSetup 189 // and EpochCommit service event. This is used for converting service events to 190 // inmem.Epoch. 191 type committedEpoch struct { 192 setupEpoch 193 commitEvent *flow.EpochCommit 194 } 195 196 func (es *committedEpoch) Cluster(index uint) (protocol.Cluster, error) { 197 198 epochCounter := es.setupEvent.Counter 199 200 clustering, err := es.Clustering() 201 if err != nil { 202 return nil, fmt.Errorf("failed to generate clustering: %w", err) 203 } 204 205 members, ok := clustering.ByIndex(index) 206 if !ok { 207 return nil, fmt.Errorf("no cluster with index %d: %w", index, protocol.ErrClusterNotFound) 208 } 209 210 qcs := es.commitEvent.ClusterQCs 211 if uint(len(qcs)) <= index { 212 return nil, fmt.Errorf("internal data inconsistency: cannot get qc at index %d - epoch has %d clusters and %d cluster QCs", 213 index, len(clustering), len(qcs)) 214 } 215 rootQCVoteData := qcs[index] 216 217 signerIndices, err := signature.EncodeSignersToIndices(members.NodeIDs(), rootQCVoteData.VoterIDs) 218 if err != nil { 219 return nil, fmt.Errorf("could not encode signer indices for rootQCVoteData.VoterIDs: %w", err) 220 } 221 222 rootBlock := cluster.CanonicalRootBlock(epochCounter, members) 223 rootQC := &flow.QuorumCertificate{ 224 View: rootBlock.Header.View, 225 BlockID: rootBlock.ID(), 226 SignerIndices: signerIndices, 227 SigData: rootQCVoteData.SigData, 228 } 229 230 cluster, err := ClusterFromEncodable(EncodableCluster{ 231 Index: index, 232 Counter: epochCounter, 233 Members: members, 234 RootBlock: rootBlock, 235 RootQC: rootQC, 236 }) 237 return cluster, err 238 } 239 240 func (es *committedEpoch) ClusterByChainID(chainID flow.ChainID) (protocol.Cluster, error) { 241 clustering, err := es.Clustering() 242 if err != nil { 243 return nil, fmt.Errorf("failed to generate clustering: %w", err) 244 } 245 246 for i, cl := range clustering { 247 if cluster.CanonicalClusterID(es.setupEvent.Counter, cl.NodeIDs()) == chainID { 248 cl, err := es.Cluster(uint(i)) 249 if err != nil { 250 return nil, fmt.Errorf("could not retrieve known existing cluster (idx=%d, id=%s): %v", i, chainID, err) 251 } 252 return cl, nil 253 } 254 } 255 return nil, protocol.ErrClusterNotFound 256 } 257 258 func (es *committedEpoch) DKG() (protocol.DKG, error) { 259 // filter initial participants to valid DKG participants 260 participants := es.setupEvent.Participants.Filter(filter.IsValidDKGParticipant) 261 lookup, err := flow.ToDKGParticipantLookup(participants, es.commitEvent.DKGParticipantKeys) 262 if err != nil { 263 return nil, fmt.Errorf("could not construct dkg lookup: %w", err) 264 } 265 266 dkg, err := DKGFromEncodable(EncodableDKG{ 267 GroupKey: encodable.RandomBeaconPubKey{ 268 PublicKey: es.commitEvent.DKGGroupKey, 269 }, 270 Participants: lookup, 271 }) 272 return dkg, err 273 } 274 275 // startedEpoch represents an epoch (with counter N) that has started, but there is no _finalized_ transition 276 // to the next epoch yet. Note that nodes can already be in views belonging to the _next_ Epoch, and it is 277 // possible that there are already unfinalized blocks in that next epoch. However, without finalized blocks 278 // in Epoch N+1, there is no definition of "last block" for Epoch N. 279 // 280 // startedEpoch has all the information of a committedEpoch, plus the epoch's first block height. 281 type startedEpoch struct { 282 committedEpoch 283 firstHeight uint64 284 } 285 286 func (e *startedEpoch) FirstHeight() (uint64, error) { 287 return e.firstHeight, nil 288 } 289 290 // endedEpoch is an epoch which has ended (ie. the previous epoch). It has all the 291 // information of a startedEpoch, plus the epoch's final block height. 292 type endedEpoch struct { 293 startedEpoch 294 finalHeight uint64 295 } 296 297 func (e *endedEpoch) FinalHeight() (uint64, error) { 298 return e.finalHeight, nil 299 } 300 301 // NewSetupEpoch returns a memory-backed epoch implementation based on an 302 // EpochSetup event. Epoch information available after the setup phase will 303 // not be accessible in the resulting epoch instance. 304 // No errors are expected during normal operations. 305 func NewSetupEpoch(setupEvent *flow.EpochSetup) protocol.Epoch { 306 return &setupEpoch{ 307 setupEvent: setupEvent, 308 } 309 } 310 311 // NewCommittedEpoch returns a memory-backed epoch implementation based on an 312 // EpochSetup and EpochCommit events. 313 // No errors are expected during normal operations. 314 func NewCommittedEpoch(setupEvent *flow.EpochSetup, commitEvent *flow.EpochCommit) protocol.Epoch { 315 return &committedEpoch{ 316 setupEpoch: setupEpoch{ 317 setupEvent: setupEvent, 318 }, 319 commitEvent: commitEvent, 320 } 321 } 322 323 // NewStartedEpoch returns a memory-backed epoch implementation based on an 324 // EpochSetup and EpochCommit events, and the epoch's first block height. 325 // No errors are expected during normal operations. 326 func NewStartedEpoch(setupEvent *flow.EpochSetup, commitEvent *flow.EpochCommit, firstHeight uint64) protocol.Epoch { 327 return &startedEpoch{ 328 committedEpoch: committedEpoch{ 329 setupEpoch: setupEpoch{ 330 setupEvent: setupEvent, 331 }, 332 commitEvent: commitEvent, 333 }, 334 firstHeight: firstHeight, 335 } 336 } 337 338 // NewEndedEpoch returns a memory-backed epoch implementation based on an 339 // EpochSetup and EpochCommit events, and the epoch's final block height. 340 // No errors are expected during normal operations. 341 func NewEndedEpoch(setupEvent *flow.EpochSetup, commitEvent *flow.EpochCommit, firstHeight, finalHeight uint64) protocol.Epoch { 342 return &endedEpoch{ 343 startedEpoch: startedEpoch{ 344 committedEpoch: committedEpoch{ 345 setupEpoch: setupEpoch{ 346 setupEvent: setupEvent, 347 }, 348 commitEvent: commitEvent, 349 }, 350 firstHeight: firstHeight, 351 }, 352 finalHeight: finalHeight, 353 } 354 }