-
Notifications
You must be signed in to change notification settings - Fork 179
/
signature.go
117 lines (105 loc) · 6.48 KB
/
signature.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package hotstuff
import (
"github.com/onflow/flow-go/crypto"
"github.com/onflow/flow-go/model/flow"
)
// RandomBeaconReconstructor encapsulates all methods needed by a Hotstuff leader to validate the
// beacon votes and reconstruct a beacon signature.
// The random beacon methods are based on a threshold signature scheme.
type RandomBeaconReconstructor interface {
// Verify verifies the signature share under the signer's public key and the message agreed upon.
// The function is thread-safe and wait-free (i.e. allowing arbitrary many routines to
// execute the business logic, without interfering with each other).
// It allows concurrent verification of the given signature.
// Returns :
// - model.InvalidSignerError if signerIndex is invalid
// - model.ErrInvalidSignature if signerID is valid but signature is cryptographically invalid
// - other error if there is an unexpected exception.
Verify(signerID flow.Identifier, sig crypto.Signature) error
// TrustedAdd adds a share to the internal signature shares store.
// There is no pre-check of the signature's validity _before_ adding it.
// It is the caller's responsibility to make sure the signature was previously verified.
// Nevertheless, the implementation guarantees safety (only correct threshold signatures
// are returned) through a post-check (verifying the threshold signature
// _after_ reconstruction before returning it).
// The function is thread-safe but locks its internal state, thereby permitting only
// one routine at a time to add a signature.
// Returns:
// - (true, nil) if the signature has been added, and enough shares have been collected.
// - (false, nil) if the signature has been added, but not enough shares were collected.
// - (false, error) if there is any exception adding the signature share.
// - model.InvalidSignerError if signerIndex is invalid (out of the valid range)
// - model.DuplicatedSignerError if the signer has been already added
// - other error if there is an unexpected exception.
TrustedAdd(signerID flow.Identifier, sig crypto.Signature) (EnoughShares bool, err error)
// EnoughShares indicates whether enough shares have been accumulated in order to reconstruct
// a group signature. The function is thread-safe.
EnoughShares() bool
// Reconstruct reconstructs the group signature. The function is thread-safe but locks
// its internal state, thereby permitting only one routine at a time.
//
// Returns:
// - (signature, nil) if no error occurred
// - (nil, model.InsufficientSignaturesError) if not enough shares were collected
// - (nil, model.InvalidSignatureIncluded) if at least one collected share does not serialize to a valid BLS signature,
// or if the constructed signature failed to verify against the group public key and stored message. This post-verification
// is required for safety, as `TrustedAdd` allows adding invalid signatures.
// - (nil, error) for any other unexpected error.
Reconstruct() (crypto.Signature, error)
}
// WeightedSignatureAggregator aggregates signatures of the same signature scheme and the
// same message from different signers. The public keys and message are agreed upon upfront.
// It is also recommended to only aggregate signatures generated with keys representing
// equivalent security-bit level.
// Furthermore, a weight [unsigned int64] is assigned to each signer ID. The
// WeightedSignatureAggregator internally tracks the total weight of all collected signatures.
// Implementations must be concurrency safe.
type WeightedSignatureAggregator interface {
// Verify verifies the signature under the stored public keys and message.
// Expected errors during normal operations:
// - model.InvalidSignerError if signerID is invalid (not a consensus participant)
// - model.ErrInvalidSignature if signerID is valid but signature is cryptographically invalid
Verify(signerID flow.Identifier, sig crypto.Signature) error
// TrustedAdd adds a signature to the internal set of signatures and adds the signer's
// weight to the total collected weight, iff the signature is _not_ a duplicate. The
// total weight of all collected signatures (excluding duplicates) is returned regardless
// of any returned error.
// Expected errors during normal operations:
// - model.InvalidSignerError if signerID is invalid (not a consensus participant)
// - model.DuplicatedSignerError if the signer has been already added
TrustedAdd(signerID flow.Identifier, sig crypto.Signature) (totalWeight uint64, exception error)
// TotalWeight returns the total weight presented by the collected signatures.
TotalWeight() uint64
// Aggregate aggregates the signatures and returns the aggregated signature.
// The function performs a final verification and errors if the aggregated
// signature is not valid. This is required for the function safety since
// `TrustedAdd` allows adding invalid signatures.
// Expected errors during normal operations:
// - model.InsufficientSignaturesError if no signatures have been added yet
// - model.InvalidSignatureIncludedError if some signature(s), included via TrustedAdd, are invalid
Aggregate() ([]flow.Identifier, []byte, error)
}
// BlockSignatureData is an intermediate struct for Packer to pack the
// aggregated signature data into raw bytes or unpack from raw bytes.
type BlockSignatureData struct {
StakingSigners []flow.Identifier
RandomBeaconSigners []flow.Identifier
AggregatedStakingSig []byte // if BLS is used, this is equivalent to crypto.Signature
AggregatedRandomBeaconSig []byte // if BLS is used, this is equivalent to crypto.Signature
ReconstructedRandomBeaconSig crypto.Signature
}
// Packer packs aggregated signature data into raw bytes to be used in block header.
type Packer interface {
// Pack serializes the provided BlockSignatureData into a precursor format of a QC.
// blockID is the block that the aggregated signature is for.
// sig is the aggregated signature data.
// Expected error returns during normal operations:
// * none; all errors are symptoms of inconsistent input data or corrupted internal state.
Pack(blockID flow.Identifier, sig *BlockSignatureData) (signerIndices []byte, sigData []byte, err error)
// Unpack de-serializes the provided signature data.
// sig is the aggregated signature data
// It returns:
// - (sigData, nil) if successfully unpacked the signature data
// - (nil, model.InvalidFormatError) if failed to unpack the signature data
Unpack(signerIdentities flow.IdentityList, sigData []byte) (*BlockSignatureData, error)
}