11import 'dart:typed_data' ;
2+ import 'package:coinlib/coinlib.dart' ;
23import 'package:coinlib/src/crypto/random.dart' ;
34import 'heap.dart' ;
45
@@ -24,7 +25,7 @@ abstract class Secp256k1Base<
2425 CtxPtr , UCharPtr , PubKeyPtr , SizeTPtr , SignaturePtr ,
2526 RecoverableSignaturePtr , KeyPairPtr , XPubKeyPtr , IntPtr , MuSigAggCachePtr ,
2627 PubKeyPtrPtr , MuSigSecNoncePtr , MuSigPubNoncePtr , MuSigAggNoncePtr ,
27- MuSigPubNoncePtrPtr , MuSigSessionPtr , NullPtr
28+ MuSigPubNoncePtrPtr , MuSigSessionPtr , MuSigPartialSigPtr , NullPtr
2829> {
2930
3031 static const contextNone = 1 ;
@@ -39,6 +40,7 @@ abstract class Secp256k1Base<
3940 static const sigSize = 64 ;
4041 static const derSigSize = 72 ;
4142 static const muSigPubNonceSize = 66 ;
43+ static const muSigPartialSigSize = 32 ;
4244 static const recSigSize = 65 ;
4345 static const keyPairSize = 96 ;
4446 static const xonlySize = 32 ;
@@ -125,6 +127,16 @@ abstract class Secp256k1Base<
125127 CtxPtr , MuSigSessionPtr , MuSigAggNoncePtr , UCharPtr , MuSigAggCachePtr ,
126128 NullPtr ,
127129 ) extMuSigNonceProcess;
130+ late int Function (
131+ CtxPtr , MuSigPartialSigPtr , MuSigSecNoncePtr , KeyPairPtr , MuSigAggCachePtr ,
132+ MuSigSessionPtr ,
133+ ) extMuSigPartialSign;
134+ late int Function (
135+ CtxPtr , MuSigPartialSigPtr , UCharPtr ,
136+ ) extMuSigPartialSigParse;
137+ late int Function (
138+ CtxPtr , UCharPtr , MuSigPartialSigPtr ,
139+ ) extMuSigPartialSigSerialize;
128140
129141 // Heap arrays
130142
@@ -640,8 +652,8 @@ abstract class Secp256k1Base<
640652
641653 }
642654
643- /// Returns an opaque allocated public MuSig2 nonce from the 66-byte [bytes] .
644- /// If the nonce is invalid, [Secp256k1Exception] may be thrown.
655+ /// Returns an opaque public MuSig2 nonce from the 66-byte [bytes] . If the
656+ /// nonce is invalid, [Secp256k1Exception] may be thrown.
645657 OpaqueGeneric <MuSigPubNoncePtr > muSigParsePublicNonce (Uint8List bytes) {
646658 _requireLoad ();
647659
@@ -660,6 +672,7 @@ abstract class Secp256k1Base<
660672
661673 }
662674
675+ /// Obtains the 66 byte serialised public MuSig nonce
663676 Uint8List muSigSerialisePublicNonce (OpaqueGeneric <MuSigPubNoncePtr > nonce) {
664677 _requireLoad ();
665678 extMuSigPubNonceSerialize (ctxPtr, muSigPubNonceArray.ptr, nonce._heap.ptr);
@@ -712,6 +725,65 @@ abstract class Secp256k1Base<
712725
713726 }
714727
728+ /// Produces a partial signature for the MuSig signing [session] using the
729+ /// [secNonce] , key [cache] and [privKeyBytes] .
730+ ///
731+ /// The caller must ensure that the private key scalar is 32-bytes.
732+ OpaqueGeneric <MuSigPartialSigPtr > muSigPartialSign (
733+ OpaqueGeneric <MuSigSecNoncePtr > secNonce,
734+ Uint8List privKeyBytes,
735+ OpaqueGeneric <MuSigAggCachePtr > cache,
736+ OpaqueGeneric <MuSigSessionPtr > session,
737+ ) {
738+ _requireLoad ();
739+
740+ _parsePrivKeyIntoKeyPairPtr (privKeyBytes);
741+
742+ final partialSig = allocMuSigPartialSig ();
743+
744+ if (
745+ extMuSigPartialSign (
746+ ctxPtr, partialSig.ptr, secNonce._heap.ptr, keyPair.ptr,
747+ cache._heap.ptr, session._heap.ptr,
748+ ) != 1
749+ ) {
750+ throw Secp256k1Exception ("Could not create partial MuSig signature" );
751+ }
752+
753+ return OpaqueGeneric (partialSig);
754+
755+ }
756+
757+ /// Returns an opaque MuSig2 partial signature from the 32-byte [bytes] .
758+ /// If the partial signature is invalid, [Secp256k1Exception] may be thrown.
759+ OpaqueGeneric <MuSigPartialSigPtr > muSigParsePartialSig (Uint8List bytes) {
760+ _requireLoad ();
761+
762+ if (bytes.length != muSigPartialSigSize) {
763+ throw Secp256k1Exception ("MuSig partial signature size must be 32" );
764+ }
765+
766+ // Reuse scalarArray as it is 32 bytes
767+ scalarArray.load (bytes);
768+ final partialSig = allocMuSigPartialSig ();
769+
770+ if (extMuSigPartialSigParse (ctxPtr, partialSig.ptr, scalarArray.ptr) != 1 ) {
771+ throw Secp256k1Exception ("Invalid MuSig partial signature" );
772+ }
773+
774+ return OpaqueGeneric (partialSig);
775+
776+ }
777+
778+ /// Obtains the serialised 32 bytes of a MuSig partial signature
779+ Uint8List muSigSerialisePartialSig (
780+ OpaqueGeneric <MuSigPartialSigPtr > partialSig,
781+ ) {
782+ _requireLoad ();
783+ extMuSigPartialSigSerialize (ctxPtr, scalarArray.ptr, partialSig._heap.ptr);
784+ return scalarArray.copy;
785+ }
786+
715787 /// Specialised sub-classes should override to allocate a [size] number of
716788 /// secp256k1_pubkey and then alloate and set an array of pointers on the heap
717789 /// to them.
@@ -745,4 +817,8 @@ abstract class Secp256k1Base<
745817 /// secp256k1_musig_session on the heap.
746818 Heap <MuSigSessionPtr > allocMuSigSession ();
747819
820+ /// Specialised sub-classes should override to allocate an
821+ /// secp256k1_musig_partial_sig on the heap.
822+ Heap <MuSigPartialSigPtr > allocMuSigPartialSig ();
823+
748824}
0 commit comments