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 }