@@ -3,55 +3,6 @@ part of "library.dart";
33/// Maps the public key of a participant to their public nonce
44typedef KeyToNonceMap = Map <ECPublicKey , MuSigPublicNonce >;
55
6- class InvalidMuSigPublicNonce implements Exception {}
7-
8- /// The public nonce of a participant for a single signing session only.
9- class MuSigPublicNonce {
10-
11- final OpaqueMuSigPublicNonce _underlying;
12- /// The serialised bytes that can be shared with other signers
13- final Uint8List bytes;
14-
15- MuSigPublicNonce ._(this ._underlying, this .bytes);
16- MuSigPublicNonce ._fromUnderlying (this ._underlying)
17- : bytes = secp256k1.muSigSerialisePublicNonce (_underlying);
18-
19- /// Creates the public nonce from the [bytes] . If the [bytes] are invalid,
20- /// [InvalidMuSigPublicNonce] will be thrown.
21- factory MuSigPublicNonce .fromBytes (Uint8List bytes) {
22- try {
23- return MuSigPublicNonce ._(secp256k1.muSigParsePublicNonce (bytes), bytes);
24- } on Secp256k1Exception {
25- throw InvalidMuSigPublicNonce ();
26- }
27- }
28-
29- }
30-
31- class InvalidMuSigPartialSig implements Exception {}
32-
33- /// The partial signature from a participant that needs to be shared.
34- class MuSigPartialSig {
35-
36- final OpaqueMuSigPartialSig _underlying;
37- final Uint8List bytes;
38-
39- MuSigPartialSig ._(this ._underlying, this .bytes);
40- MuSigPartialSig ._fromUnderlying (this ._underlying)
41- : bytes = secp256k1.muSigSerialisePartialSig (_underlying);
42-
43- /// Creates the partial signature from the [bytes] . If the [bytes] are
44- /// invalid, [InvalidMuSigPartialSig] will be thrown.
45- factory MuSigPartialSig .fromBytes (Uint8List bytes) {
46- try {
47- return MuSigPartialSig ._(secp256k1.muSigParsePartialSig (bytes), bytes);
48- } on Secp256k1Exception {
49- throw InvalidMuSigPartialSig ();
50- }
51- }
52-
53- }
54-
556/// A MuSig signing session state to be used for one signing session only.
567///
578/// This class is stateful unlike most of the classes in the library. This is to
@@ -69,8 +20,10 @@ class MuSigStatefulSigningSession {
6920 late final OpaqueMuSigSecretNonce _ourSecretNonce;
7021
7122 OpaqueMuSigSession ? _underlyingSession;
23+ bool _isAdaptor = false ;
7224 KeyToNonceMap ? _otherNonces;
73- Map <ECPublicKey , MuSigPartialSig > _partialSigs = {};
25+ OpaqueMuSigPartialSig ? _ourPartialSig;
26+ final Map <ECPublicKey , OpaqueMuSigPartialSig > _partialSigs = {};
7427
7528 /// Starts a signing session with the MuSig [keys] and specifying the public
7629 /// key for the signer with [ourPublicKey] .
@@ -156,13 +109,13 @@ class MuSigStatefulSigningSession {
156109 adaptor? .data,
157110 );
158111 _otherNonces = otherNonces;
112+ _isAdaptor = adaptor != null ;
159113
160114 // Produce partial signature
161- return MuSigPartialSig ._fromUnderlying (
162- secp256k1.muSigPartialSign (
163- _ourSecretNonce, privKey.data, keys._aggCache, _underlyingSession! ,
164- ),
115+ _ourPartialSig = secp256k1.muSigPartialSign (
116+ _ourSecretNonce, privKey.data, keys._aggCache, _underlyingSession! ,
165117 );
118+ return MuSigPartialSig ._fromUnderlying (_ourPartialSig! );
166119
167120 }
168121
@@ -209,7 +162,7 @@ class MuSigStatefulSigningSession {
209162 );
210163
211164 if (valid) {
212- _partialSigs[participantKey] = partialSig;
165+ _partialSigs[participantKey] = partialSig._underlying ;
213166 }
214167
215168 return valid;
@@ -221,4 +174,36 @@ class MuSigStatefulSigningSession {
221174 bool havePartialSignature (ECPublicKey participantKey) =>
222175 _partialSigs.containsKey (participantKey);
223176
177+ MuSigResult finish () {
178+
179+ if (_underlyingSession == null ) {
180+ throw StateError ("Need to call sign before finishing" );
181+ }
182+
183+ final actualSigs = _partialSigs.length;
184+ final reqSigs = keys.pubKeys.length - 1 ;
185+ if (actualSigs != reqSigs) {
186+ throw StateError (
187+ "Need $reqSigs partial signatures. Only have $actualSigs " ,
188+ );
189+ }
190+
191+ final sig = SchnorrSignature (
192+ secp256k1.muSigSignatureAggregate (
193+ { _ourPartialSig! , ..._partialSigs.values },
194+ _underlyingSession! ,
195+ ),
196+ );
197+
198+ return _isAdaptor
199+ ? MuSigResultAdaptor ._(
200+ SchnorrAdaptorSignature (
201+ sig,
202+ secp256k1.muSigNonceParity (_underlyingSession! ),
203+ ),
204+ )
205+ : MuSigResultComplete ._(sig);
206+
207+ }
208+
224209}
0 commit comments