github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/verification/staking_verifier.go (about) 1 package verification 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/crypto/hash" 7 8 "github.com/onflow/flow-go/consensus/hotstuff" 9 "github.com/onflow/flow-go/consensus/hotstuff/model" 10 "github.com/onflow/flow-go/model/flow" 11 msig "github.com/onflow/flow-go/module/signature" 12 ) 13 14 // StakingVerifier is a verifier capable of verifying staking signature for each 15 // verifying operation. It's used primarily with collection cluster where hotstuff without beacon signers is used. 16 type StakingVerifier struct { 17 stakingHasher hash.Hasher 18 timeoutObjectHasher hash.Hasher 19 } 20 21 var _ hotstuff.Verifier = (*StakingVerifier)(nil) 22 23 // NewStakingVerifier creates a new single verifier with the given dependencies. 24 func NewStakingVerifier() *StakingVerifier { 25 return &StakingVerifier{ 26 stakingHasher: msig.NewBLSHasher(msig.CollectorVoteTag), 27 timeoutObjectHasher: msig.NewBLSHasher(msig.CollectorTimeoutTag), 28 } 29 } 30 31 // VerifyVote verifies the validity of a single signature from a vote. 32 // Usually this method is only used to verify the proposer's vote, which is 33 // the vote included in a block proposal. 34 // The implementation returns the following sentinel errors: 35 // - model.ErrInvalidSignature is the signature is invalid 36 // - unexpected errors should be treated as symptoms of bugs or uncovered 37 // edge cases in the logic (i.e. as fatal) 38 func (v *StakingVerifier) VerifyVote(signer *flow.IdentitySkeleton, sigData []byte, view uint64, blockID flow.Identifier) error { 39 40 // create the to-be-signed message 41 msg := MakeVoteMessage(view, blockID) 42 43 // verify each signature against the message 44 stakingValid, err := signer.StakingPubKey.Verify(sigData, msg, v.stakingHasher) 45 if err != nil { 46 return fmt.Errorf("internal error while verifying staking signature: %w", err) 47 } 48 if !stakingValid { 49 return fmt.Errorf("invalid sig for block %v: %w", blockID, model.ErrInvalidSignature) 50 } 51 52 return nil 53 } 54 55 // VerifyQC checks the cryptographic validity of the QC's `sigData` for the 56 // given block. It is the responsibility of the calling code to ensure 57 // that all `signers` are authorized, without duplicates. Return values: 58 // - nil if `sigData` is cryptographically valid 59 // - model.InvalidFormatError if `sigData` has an incompatible format 60 // - model.InsufficientSignaturesError if `signers` is empty. 61 // - model.ErrInvalidSignature if a signature is invalid 62 // - unexpected errors should be treated as symptoms of bugs or uncovered 63 // edge cases in the logic (i.e. as fatal) 64 // 65 // In the single verification case, `sigData` represents a single signature (`crypto.Signature`). 66 func (v *StakingVerifier) VerifyQC(signers flow.IdentitySkeletonList, sigData []byte, view uint64, blockID flow.Identifier) error { 67 msg := MakeVoteMessage(view, blockID) 68 69 err := verifyAggregatedSignatureOneMessage(signers.PublicStakingKeys(), sigData, v.stakingHasher, msg) 70 if err != nil { 71 return fmt.Errorf("verifying aggregated staking signature failed for block %v: %w", blockID, err) 72 } 73 74 return nil 75 } 76 77 // VerifyTC checks cryptographic validity of the TC's `sigData` w.r.t. the 78 // given view. It is the responsibility of the calling code to ensure 79 // that all `signers` are authorized, without duplicates. Return values: 80 // - nil if `sigData` is cryptographically valid 81 // - model.InsufficientSignaturesError if `signers is empty. 82 // - model.InvalidFormatError if `signers`/`highQCViews` have differing lengths 83 // - model.ErrInvalidSignature if a signature is invalid 84 // - unexpected errors should be treated as symptoms of bugs or uncovered 85 // edge cases in the logic (i.e. as fatal) 86 func (v *StakingVerifier) VerifyTC(signers flow.IdentitySkeletonList, sigData []byte, view uint64, highQCViews []uint64) error { 87 return verifyTCSignatureManyMessages(signers.PublicStakingKeys(), sigData, view, highQCViews, v.timeoutObjectHasher) 88 }