1+ import 'dart:typed_data' ;
2+ import 'package:coinlib/src/common/bytes.dart' ;
13import 'package:coinlib/src/crypto/ec_private_key.dart' ;
24import 'package:coinlib/src/crypto/ec_public_key.dart' ;
35import 'package:coinlib/src/secp256k1/secp256k1.dart' ;
@@ -12,7 +14,9 @@ class MuSigPublicKeys {
1214
1315 late final MuSigCache _aggCache;
1416
15- MuSigPublicKeys (this .pubKeys) {
17+ MuSigPublicKeys ._(this .pubKeys, this .aggregate, this ._aggCache);
18+
19+ factory MuSigPublicKeys (Set <ECPublicKey > pubKeys) {
1620
1721 if (pubKeys.isEmpty) {
1822 throw ArgumentError .value (pubKeys, "pubKeys" , "should not be empty" );
@@ -21,11 +25,20 @@ class MuSigPublicKeys {
2125 final (bytes, cache) = secp256k1.muSigAgggregate (
2226 pubKeys.map ((pk) => pk.data).toList (),
2327 );
24- aggregate = ECPublicKey . fromXOnly (bytes);
25- _aggCache = cache;
28+
29+ return MuSigPublicKeys ._(pubKeys, ECPublicKey . fromXOnly (bytes), cache) ;
2630
2731 }
2832
33+ /// Tweaks as an x-only aggregate public key
34+ MuSigPublicKeys tweak (Uint8List scalar) {
35+ checkScalar (scalar);
36+ final (keyBytes, cache) = secp256k1.muSigTweakXOnly (
37+ _aggCache, scalar,
38+ );
39+ return MuSigPublicKeys ._(pubKeys, ECPublicKey (keyBytes).xonly, cache);
40+ }
41+
2942}
3043
3144/// The private MuSig2 information for a participant
@@ -34,7 +47,13 @@ class MuSigPrivate {
3447 final ECPrivateKey privateKey;
3548 final MuSigPublicKeys public;
3649
50+ MuSigPrivate ._(this .privateKey, this .public);
51+
3752 MuSigPrivate (this .privateKey, Set <ECPublicKey > otherKeys)
3853 : public = MuSigPublicKeys ({ privateKey.pubkey, ...otherKeys });
3954
55+ MuSigPrivate tweak (Uint8List scalar) => MuSigPrivate ._(
56+ privateKey, public.tweak (scalar),
57+ );
58+
4059}
0 commit comments