github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/blockproducer/block_producer.go (about) 1 package blockproducer 2 3 import ( 4 "fmt" 5 6 "github.com/koko1123/flow-go-1/consensus/hotstuff" 7 "github.com/koko1123/flow-go-1/consensus/hotstuff/model" 8 "github.com/koko1123/flow-go-1/model/flow" 9 "github.com/koko1123/flow-go-1/module" 10 ) 11 12 // BlockProducer is responsible for producing new block proposals 13 type BlockProducer struct { 14 signer hotstuff.Signer 15 committee hotstuff.Committee 16 builder module.Builder 17 } 18 19 // New creates a new BlockProducer which wraps the chain compliance layer block builder 20 // to provide hotstuff with block proposals. 21 func New(signer hotstuff.Signer, committee hotstuff.Committee, builder module.Builder) (*BlockProducer, error) { 22 bp := &BlockProducer{ 23 signer: signer, 24 committee: committee, 25 builder: builder, 26 } 27 return bp, nil 28 } 29 30 // MakeBlockProposal will build a proposal for the given view with the given QC 31 func (bp *BlockProducer) MakeBlockProposal(qc *flow.QuorumCertificate, view uint64) (*model.Proposal, error) { 32 // the custom functions allows us to set some custom fields on the block; 33 // in hotstuff, we use this for view number and signature-related fields 34 setHotstuffFields := func(header *flow.Header) error { 35 header.View = view 36 header.ParentVoterIndices = qc.SignerIndices 37 header.ParentVoterSigData = qc.SigData 38 header.ProposerID = bp.committee.Self() 39 40 // turn the header into a block header proposal as known by hotstuff 41 block := model.Block{ 42 BlockID: header.ID(), 43 View: view, 44 ProposerID: header.ProposerID, 45 QC: qc, 46 PayloadHash: header.PayloadHash, 47 Timestamp: header.Timestamp, 48 } 49 50 // then sign the proposal 51 proposal, err := bp.signer.CreateProposal(&block) 52 if err != nil { 53 return fmt.Errorf("could not sign block proposal: %w", err) 54 } 55 56 header.ProposerSigData = proposal.SigData 57 return nil 58 } 59 60 // retrieve a fully built block header from the builder 61 header, err := bp.builder.BuildOn(qc.BlockID, setHotstuffFields) 62 if err != nil { 63 return nil, fmt.Errorf("could not build block proposal on top of %v: %w", qc.BlockID, err) 64 } 65 66 // turn the signed flow header into a proposal 67 proposal := model.ProposalFromFlow(header, qc.View) 68 69 return proposal, nil 70 }