github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/signature/randombeacon_reconstructor.go (about)

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