github.com/onflow/flow-go@v0.33.17/consensus/hotstuff/verification/staking_verifier.go (about)

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