@@ -9,16 +9,16 @@ import (
99 "github.com/rs/zerolog"
1010 "golang.org/x/exp/slices"
1111
12- "github.com/onflow/flow-go/state/protocol/prg"
13-
1412 "github.com/onflow/flow-go/cmd/util/cmd/common"
13+ hotstuff "github.com/onflow/flow-go/consensus/hotstuff/model"
1514 "github.com/onflow/flow-go/fvm/systemcontracts"
1615 "github.com/onflow/flow-go/model/bootstrap"
1716 model "github.com/onflow/flow-go/model/bootstrap"
1817 "github.com/onflow/flow-go/model/cluster"
1918 "github.com/onflow/flow-go/model/flow"
2019 "github.com/onflow/flow-go/model/flow/filter"
2120 "github.com/onflow/flow-go/state/protocol/inmem"
21+ "github.com/onflow/flow-go/state/protocol/prg"
2222)
2323
2424// GenerateRecoverEpochTxArgs generates the required transaction arguments for the `recoverEpoch` transaction.
@@ -303,8 +303,7 @@ func GenerateRecoverTxArgsWithDKG(
303303// - nodeInfos: list of NodeInfos (must contain all internal nodes)
304304// - clusterBlocks: list of root blocks (one for each cluster)
305305// Returns:
306- // - flow.AssignmentList: the generated assignment list.
307- // - flow.ClusterList: the generate collection cluster list.
306+ // - The list of quorum certificates for all clusters.
308307func ConstructRootQCsForClusters (log zerolog.Logger , clusterList flow.ClusterList , nodeInfos []bootstrap.NodeInfo , clusterBlocks []* cluster.Block ) []* flow.QuorumCertificate {
309308 if len (clusterBlocks ) != len (clusterList ) {
310309 log .Fatal ().Int ("len(clusterBlocks)" , len (clusterBlocks )).Int ("len(clusterList)" , len (clusterList )).
@@ -326,6 +325,42 @@ func ConstructRootQCsForClusters(log zerolog.Logger, clusterList flow.ClusterLis
326325 return qcs
327326}
328327
328+ // ConstructClusterRootQCsFromVotes constructs a root QC for each cluster in the list, based on the provided votes.
329+ // Args:
330+ // - log: the logger instance.
331+ // - clusterList: list of clusters
332+ // - nodeInfos: list of NodeInfos (must contain all internal nodes)
333+ // - clusterBlocks: list of root blocks (one for each cluster)
334+ // - votes: lists of votes for each cluster (one list for each cluster)
335+ // Returns:
336+ // - the list of quorum certificates for all clusters
337+ func ConstructClusterRootQCsFromVotes (log zerolog.Logger , clusterList flow.ClusterList , nodeInfos []bootstrap.NodeInfo , clusterBlocks []* cluster.Block , votes [][]* hotstuff.Vote ) []* flow.QuorumCertificate {
338+ if len (clusterBlocks ) != len (clusterList ) {
339+ log .Fatal ().Int ("len(clusterBlocks)" , len (clusterBlocks )).Int ("len(clusterList)" , len (clusterList )).
340+ Msg ("number of clusters needs to equal number of cluster blocks" )
341+ }
342+ if len (votes ) != len (clusterList ) {
343+ log .Fatal ().Int ("len(votes)" , len (votes )).Int ("len(clusterList)" , len (clusterList )).
344+ Msg ("number of groups of votes needs to equal number of clusters" )
345+ }
346+
347+ qcs := make ([]* flow.QuorumCertificate , len (clusterBlocks ))
348+ for i , clusterMembers := range clusterList {
349+ clusterBlock := clusterBlocks [i ]
350+ clusterVotes := votes [i ]
351+ signers := filterClusterSigners (clusterMembers , nodeInfos )
352+ log .Info ().Msgf ("producing QC for cluster (index: %d, size: %d) from %d votes" , i , len (clusterMembers ), len (votes ))
353+
354+ qc , err := GenerateClusterRootQCFromVotes (signers , clusterMembers , clusterBlock , clusterVotes )
355+ if err != nil {
356+ log .Fatal ().Err (err ).Int ("cluster index" , i ).Msg ("generating collector cluster root QC failed" )
357+ }
358+ qcs [i ] = qc
359+ }
360+
361+ return qcs
362+ }
363+
329364// Filters a list of nodes to include only nodes that will sign the QC for the
330365// given cluster. The resulting list of nodes is only nodes that are in the
331366// given cluster AND are not partner nodes (ie. we have the private keys).
0 commit comments