github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/verification/staking_signer.go (about) 1 package verification 2 3 import ( 4 "fmt" 5 6 "github.com/koko1123/flow-go-1/consensus/hotstuff/model" 7 "github.com/koko1123/flow-go-1/model/flow" 8 "github.com/koko1123/flow-go-1/module" 9 msig "github.com/koko1123/flow-go-1/module/signature" 10 "github.com/onflow/flow-go/crypto/hash" 11 ) 12 13 // StakingSigner creates votes for the collector clusters consensus. 14 // When a participant votes for a block, it _always_ provide the staking signature 15 // as part of their vote. StakingSigner is responsible for creating correctly 16 // signed proposals and votes. 17 type StakingSigner struct { 18 me module.Local 19 stakingHasher hash.Hasher 20 signerID flow.Identifier 21 } 22 23 // NewStakingSigner instantiates a StakingSigner, which signs votes and 24 // proposals with the staking key. The generated signatures are aggregatable. 25 func NewStakingSigner( 26 me module.Local, 27 ) *StakingSigner { 28 29 sc := &StakingSigner{ 30 me: me, 31 stakingHasher: msig.NewBLSHasher(msig.CollectorVoteTag), 32 signerID: me.NodeID(), 33 } 34 return sc 35 } 36 37 // CreateProposal will create a proposal with a staking signature for the given block. 38 func (c *StakingSigner) CreateProposal(block *model.Block) (*model.Proposal, error) { 39 40 // check that the block is created by us 41 if block.ProposerID != c.signerID { 42 return nil, fmt.Errorf("can't create proposal for someone else's block") 43 } 44 45 // create the signature data 46 sigData, err := c.genSigData(block) 47 if err != nil { 48 return nil, fmt.Errorf("signing my proposal failed: %w", err) 49 } 50 51 // create the proposal 52 proposal := &model.Proposal{ 53 Block: block, 54 SigData: sigData, 55 } 56 57 return proposal, nil 58 } 59 60 // CreateVote will create a vote with a staking signature for the given block. 61 func (c *StakingSigner) CreateVote(block *model.Block) (*model.Vote, error) { 62 63 // create the signature data 64 sigData, err := c.genSigData(block) 65 if err != nil { 66 return nil, fmt.Errorf("could not create signature: %w", err) 67 } 68 69 // create the vote 70 vote := &model.Vote{ 71 View: block.View, 72 BlockID: block.BlockID, 73 SignerID: c.signerID, 74 SigData: sigData, 75 } 76 77 return vote, nil 78 } 79 80 // genSigData generates the signature data for our local node for the given block. 81 // It returns: 82 // - (stakingSig, nil) signature signed with staking key. The sig is 48 bytes long 83 // - (nil, error) if there is any exception 84 func (c *StakingSigner) genSigData(block *model.Block) ([]byte, error) { 85 // create the message to be signed and generate signatures 86 msg := MakeVoteMessage(block.View, block.BlockID) 87 88 stakingSig, err := c.me.Sign(msg, c.stakingHasher) 89 if err != nil { 90 return nil, fmt.Errorf("could not generate staking signature for block (%v) at view %v: %w", block.BlockID, block.View, err) 91 } 92 93 return stakingSig, nil 94 }