github.com/koko1123/flow-go-1@v0.29.6/cmd/bootstrap/run/cluster_qc.go (about)

     1  package run
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/rs/zerolog"
     7  
     8  	"github.com/koko1123/flow-go-1/consensus/hotstuff"
     9  	"github.com/koko1123/flow-go-1/consensus/hotstuff/committees"
    10  	"github.com/koko1123/flow-go-1/consensus/hotstuff/mocks"
    11  	"github.com/koko1123/flow-go-1/consensus/hotstuff/model"
    12  	"github.com/koko1123/flow-go-1/consensus/hotstuff/validator"
    13  	"github.com/koko1123/flow-go-1/consensus/hotstuff/verification"
    14  	"github.com/koko1123/flow-go-1/consensus/hotstuff/votecollector"
    15  	"github.com/koko1123/flow-go-1/model/bootstrap"
    16  	"github.com/koko1123/flow-go-1/model/cluster"
    17  	"github.com/koko1123/flow-go-1/model/flow"
    18  	"github.com/koko1123/flow-go-1/model/flow/order"
    19  	"github.com/koko1123/flow-go-1/module/local"
    20  )
    21  
    22  // GenerateClusterRootQC creates votes and generates a QC based on participant data
    23  func GenerateClusterRootQC(signers []bootstrap.NodeInfo, allCommitteeMembers flow.IdentityList, clusterBlock *cluster.Block) (*flow.QuorumCertificate, error) {
    24  	clusterRootBlock := model.GenesisBlockFromFlow(clusterBlock.Header)
    25  
    26  	// STEP 1: create votes for cluster root block
    27  	votes, err := createRootBlockVotes(signers, clusterRootBlock)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	// STEP 2: create VoteProcessor
    33  	ordered := allCommitteeMembers.Sort(order.Canonical)
    34  	committee, err := committees.NewStaticCommittee(ordered, flow.Identifier{}, nil, nil)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  	var createdQC *flow.QuorumCertificate
    39  	processor, err := votecollector.NewBootstrapStakingVoteProcessor(zerolog.Logger{}, committee, clusterRootBlock, func(qc *flow.QuorumCertificate) {
    40  		createdQC = qc
    41  	})
    42  	if err != nil {
    43  		return nil, fmt.Errorf("could not create cluster's StakingVoteProcessor: %w", err)
    44  	}
    45  
    46  	// STEP 3: feed the votes into the vote processor to create QC
    47  	for _, vote := range votes {
    48  		err := processor.Process(vote)
    49  		if err != nil {
    50  			return nil, fmt.Errorf("could not process vote: %w", err)
    51  		}
    52  	}
    53  	if createdQC == nil {
    54  		return nil, fmt.Errorf("not enough votes to create qc for bootstrapping")
    55  	}
    56  
    57  	// STEP 4: validate constructed QC
    58  	val, err := createClusterValidator(committee)
    59  	if err != nil {
    60  		return nil, fmt.Errorf("could not create cluster validator: %w", err)
    61  	}
    62  	err = val.ValidateQC(createdQC, clusterRootBlock)
    63  
    64  	return createdQC, err
    65  }
    66  
    67  // createClusterValidator creates validator for cluster consensus
    68  func createClusterValidator(committee hotstuff.Committee) (hotstuff.Validator, error) {
    69  	verifier := verification.NewStakingVerifier()
    70  
    71  	forks := &mocks.ForksReader{}
    72  	hotstuffValidator := validator.New(committee, forks, verifier)
    73  	return hotstuffValidator, nil
    74  }
    75  
    76  // createRootBlockVotes generates a vote for the rootBlock from each participant
    77  func createRootBlockVotes(participants []bootstrap.NodeInfo, rootBlock *model.Block) ([]*model.Vote, error) {
    78  	votes := make([]*model.Vote, 0, len(participants))
    79  	for _, participant := range participants {
    80  		// create the participant's local identity
    81  		keys, err := participant.PrivateKeys()
    82  		if err != nil {
    83  			return nil, fmt.Errorf("could not retrieve private keys for participant: %w", err)
    84  		}
    85  		me, err := local.New(participant.Identity(), keys.StakingKey)
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  
    90  		// generate root block vote
    91  		vote, err := verification.NewStakingSigner(me).CreateVote(rootBlock)
    92  		if err != nil {
    93  			return nil, fmt.Errorf("could not create cluster vote for participant %v: %w", me.NodeID(), err)
    94  		}
    95  		votes = append(votes, vote)
    96  	}
    97  	return votes, nil
    98  }