github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/hotstuff/signature/randombeacon_reconstructor.go (about)

     1  package signature
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/crypto"
     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  	"github.com/onflow/flow-go/state/protocol"
    12  )
    13  
    14  // RandomBeaconReconstructor implements hotstuff.RandomBeaconReconstructor.
    15  // The implementation wraps the hotstuff.RandomBeaconInspector and translates the signer identity into signer index.
    16  // It has knowledge about DKG to be able to map signerID to signerIndex
    17  type RandomBeaconReconstructor struct {
    18  	hotstuff.RandomBeaconInspector              // a stateful object for this epoch. It's used for both verifying all sig shares and reconstructing the threshold signature.
    19  	dkg                            hotstuff.DKG // to lookup signer index by signer ID
    20  }
    21  
    22  var _ hotstuff.RandomBeaconReconstructor = (*RandomBeaconReconstructor)(nil)
    23  
    24  func NewRandomBeaconReconstructor(dkg hotstuff.DKG, randomBeaconInspector hotstuff.RandomBeaconInspector) *RandomBeaconReconstructor {
    25  	return &RandomBeaconReconstructor{
    26  		RandomBeaconInspector: randomBeaconInspector,
    27  		dkg:                   dkg,
    28  	}
    29  }
    30  
    31  // Verify verifies the signature share under the signer's public key and the message agreed upon.
    32  // The function is thread-safe and wait-free (i.e. allowing arbitrary many routines to
    33  // execute the business logic, without interfering with each other).
    34  // It allows concurrent verification of the given signature.
    35  // Returns :
    36  //   - model.InvalidSignerError if signerID is invalid
    37  //   - model.ErrInvalidSignature if signerID is valid but signature is cryptographically invalid
    38  //   - other error if there is an unexpected exception.
    39  func (r *RandomBeaconReconstructor) Verify(signerID flow.Identifier, sig crypto.Signature) error {
    40  	signerIndex, err := r.dkg.Index(signerID)
    41  	if err != nil {
    42  		if protocol.IsIdentityNotFound(err) {
    43  			return model.NewInvalidSignerErrorf("signer %v is not a valid random beacon participant: %w", signerID, err)
    44  		}
    45  		return fmt.Errorf("internal error retrieving DKG index for %v: %w", signerID, err)
    46  	}
    47  	return r.RandomBeaconInspector.Verify(int(signerIndex), sig)
    48  }
    49  
    50  // TrustedAdd adds a share to the internal signature shares store.
    51  // There is no pre-check of the signature's validity _before_ adding it.
    52  // It is the caller's responsibility to make sure the signature was previously verified.
    53  // Nevertheless, the implementation guarantees safety (only correct threshold signatures
    54  // are returned) through a post-check (verifying the threshold signature
    55  // _after_ reconstruction before returning it).
    56  // The function is thread-safe but locks its internal state, thereby permitting only
    57  // one routine at a time to add a signature.
    58  // Returns:
    59  //   - (true, nil) if the signature has been added, and enough shares have been collected.
    60  //   - (false, nil) if the signature has been added, but not enough shares were collected.
    61  //
    62  // The following errors are expected during normal operations:
    63  //   - model.InvalidSignerError if signerIndex is invalid (out of the valid range)
    64  //   - model.DuplicatedSignerError if the signer has been already added
    65  //   - other error if there is an unexpected exception.
    66  func (r *RandomBeaconReconstructor) TrustedAdd(signerID flow.Identifier, sig crypto.Signature) (bool, error) {
    67  	signerIndex, err := r.dkg.Index(signerID)
    68  	if err != nil {
    69  		if protocol.IsIdentityNotFound(err) {
    70  			return false, model.NewInvalidSignerErrorf("signer %v is not a valid random beacon participant: %w", signerID, err)
    71  		}
    72  		return false, fmt.Errorf("internal error retrieving DKG index for %v: %w", signerID, err)
    73  	}
    74  	return r.RandomBeaconInspector.TrustedAdd(int(signerIndex), sig)
    75  }