secp256k1/
musig.rs

1//! This module implements high-level Rust bindings for a Schnorr-based
2//! multi-signature scheme called MuSig2 [paper](https://eprint.iacr.org/2020/1261).
3//! It is compatible with bip-schnorr.
4//!
5//! The documentation in this module is for reference and may not be sufficient
6//! for advanced use-cases. A full description of the C API usage along with security considerations
7//! can be found in [C-musig.md](secp256k1-sys/depend/secp256k1/src/modules/musig/musig.md).
8use core;
9use core::fmt;
10use core::mem::MaybeUninit;
11#[cfg(feature = "std")]
12use std;
13
14use crate::ffi::{self, CPtr};
15#[cfg(doc)]
16use crate::key;
17use crate::{
18    from_hex, schnorr, Error, Keypair, PublicKey, Scalar, Secp256k1, SecretKey, XOnlyPublicKey,
19};
20
21/// Serialized size (in bytes) of the aggregated nonce.
22/// The serialized form is used for transmitting or storing the aggregated nonce.
23pub const AGGNONCE_SERIALIZED_SIZE: usize = 66;
24
25/// Serialized size (in bytes) of an individual public nonce.
26/// The serialized form is used for transmission between signers.
27pub const PUBNONCE_SERIALIZED_SIZE: usize = 66;
28
29/// Serialized size (in bytes) of a partial signature.
30/// The serialized form is used for transmitting partial signatures to be
31/// aggregated into the final signature.
32pub const PART_SIG_SERIALIZED_SIZE: usize = 32;
33
34/// Musig parsing errors
35#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
36pub enum ParseError {
37    /// Parse Argument is malformed. This might occur if the point is on the secp order,
38    /// or if the secp scalar is outside of group order
39    MalformedArg,
40}
41
42#[cfg(feature = "std")]
43impl std::error::Error for ParseError {}
44
45impl fmt::Display for ParseError {
46    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
47        match *self {
48            ParseError::MalformedArg => write!(f, "Malformed parse argument"),
49        }
50    }
51}
52
53/// Session Id for a MuSig session.
54#[allow(missing_copy_implementations)]
55#[derive(Debug, Eq, PartialEq)]
56pub struct SessionSecretRand([u8; 32]);
57
58impl SessionSecretRand {
59    /// Creates a new [`SessionSecretRand`] with random bytes from the given rng
60    #[cfg(feature = "rand")]
61    pub fn from_rng<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
62        let session_secrand = crate::random_32_bytes(rng);
63        SessionSecretRand(session_secrand)
64    }
65
66    /// Creates a new [`SessionSecretRand`] with the given bytes.
67    ///
68    /// Special care must be taken that the bytes are unique for each call to
69    /// [`KeyAggCache::nonce_gen`] or [`new_nonce_pair`]. The simplest
70    /// recommendation is to use a cryptographicaly random 32-byte value.
71    ///
72    /// If the **rand** feature is enabled, [`SessionSecretRand::from_rng`] can be used to generate a
73    /// random session id.
74    ///
75    /// # Panics
76    ///
77    /// Panics if passed the all-zeros string. This is disallowed by the upstream
78    /// library. The input to this function should either be the whitened output of
79    /// a random number generator, or if that is not available, the output of a
80    /// stable monotonic counter.
81    pub fn assume_unique_per_nonce_gen(inner: [u8; 32]) -> Self {
82        // See SecretKey::eq for this "constant-time" algorithm for comparison against zero.
83        let inner_or = inner.iter().fold(0, |accum, x| accum | *x);
84        assert!(
85            unsafe { core::ptr::read_volatile(&inner_or) != 0 },
86            "session secrets may not be all zero",
87        );
88
89        SessionSecretRand(inner)
90    }
91
92    /// Obtains the inner bytes of the [`SessionSecretRand`].
93    pub fn to_byte_array(&self) -> [u8; 32] { self.0 }
94
95    /// Obtains a reference to the inner bytes of the [`SessionSecretRand`].
96    pub fn as_byte_array(&self) -> &[u8; 32] { &self.0 }
97
98    /// Obtains a mutable raw pointer to the beginning of the underlying storage.
99    ///
100    /// This is a low-level function and not exposed in the public API.
101    fn as_mut_ptr(&mut self) -> *mut u8 { self.0.as_mut_ptr() }
102}
103
104///  Cached data related to a key aggregation.
105#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
106pub struct KeyAggCache {
107    data: ffi::MusigKeyAggCache,
108    aggregated_xonly_public_key: XOnlyPublicKey,
109}
110
111impl CPtr for KeyAggCache {
112    type Target = ffi::MusigKeyAggCache;
113
114    fn as_c_ptr(&self) -> *const Self::Target { self.as_ptr() }
115
116    fn as_mut_c_ptr(&mut self) -> *mut Self::Target { self.as_mut_ptr() }
117}
118
119/// Musig tweaking related error.
120#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
121pub struct InvalidTweakErr;
122
123#[cfg(feature = "std")]
124impl std::error::Error for InvalidTweakErr {}
125
126impl fmt::Display for InvalidTweakErr {
127    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
128        write!(f, "The tweak is negation of secret key")
129    }
130}
131
132/// Low level API for starting a signing session by generating a nonce.
133///
134/// Use [`KeyAggCache::nonce_gen`] whenever
135/// possible. This API provides full flexibility in providing custom nonce generation,
136/// but should be use with care.
137///
138/// This function outputs a secret nonce that will be required for signing and a
139/// corresponding public nonce that is intended to be sent to other signers.
140///
141/// MuSig differs from regular Schnorr signing in that implementers _must_ take
142/// special care to not reuse a nonce. If you cannot provide a `sec_key`, `session_secrand`
143/// UNIFORMLY RANDOM AND KEPT SECRET (even from other signers). Refer to libsecp256k1
144/// documentation for additional considerations.
145///
146/// MuSig2 nonces can be precomputed without knowing the aggregate public key, the message to sign.
147/// Refer to libsecp256k1 documentation for additional considerations.
148///
149/// # Arguments:
150///
151/// * `session_secrand`: [`SessionSecretRand`] Uniform random identifier for this session. Each call to this
152///   function must have a UNIQUE `session_secrand`.
153/// * `sec_key`: Optional [`SecretKey`] that we will use to sign to a create partial signature. Provide this
154///   for maximal mis-use resistance.
155/// * `pub_key`: [`PublicKey`] that we will use to create partial signature. The secnonce
156///   output of this function cannot be used to sign for any other public key.
157/// * `msg`: Optional message that will be signed later on. Provide this for maximal misuse resistance.
158/// * `extra_rand`: Additional randomness for mis-use resistance. Provide this for maximal misuse resistance
159///
160/// Remember that nonce reuse will immediately leak the secret key!
161///
162/// Example:
163///
164/// ```rust
165/// # #[cfg(feature = "std")]
166/// # #[cfg(feature = "rand")] {
167/// # use secp256k1::{PublicKey, SecretKey};
168/// # use secp256k1::musig::{new_nonce_pair, SessionSecretRand};
169/// // The session id must be sampled at random. Read documentation for more details.
170/// let session_secrand = SessionSecretRand::from_rng(&mut rand::rng());
171/// let sk = SecretKey::new(&mut rand::rng());
172/// let pk = PublicKey::from_secret_key(&sk);
173///
174/// // Supply extra auxiliary randomness to prevent misuse(for example, time of day)
175/// let extra_rand : Option<[u8; 32]> = None;
176///
177/// let (_sec_nonce, _pub_nonce) = new_nonce_pair(session_secrand, None, Some(sk), pk, None, None);
178/// # }
179/// ```
180pub fn new_nonce_pair(
181    mut session_secrand: SessionSecretRand,
182    key_agg_cache: Option<&KeyAggCache>,
183    sec_key: Option<SecretKey>,
184    pub_key: PublicKey,
185    msg: Option<&[u8; 32]>,
186    extra_rand: Option<[u8; 32]>,
187) -> (SecretNonce, PublicNonce) {
188    let extra_ptr = extra_rand.as_ref().map(|e| e.as_ptr()).unwrap_or(core::ptr::null());
189    let sk_ptr = sec_key.as_ref().map(|e| e.as_c_ptr()).unwrap_or(core::ptr::null());
190    let msg_ptr = msg.as_ref().map(|e| e.as_c_ptr()).unwrap_or(core::ptr::null());
191    let cache_ptr = key_agg_cache.map(|e| e.as_ptr()).unwrap_or(core::ptr::null());
192
193    let mut seed = session_secrand.to_byte_array();
194    if let Some(bytes) = sec_key {
195        for (this, that) in seed.iter_mut().zip(bytes.to_secret_bytes().iter()) {
196            *this ^= *that;
197        }
198    }
199    if let Some(bytes) = extra_rand {
200        for (this, that) in seed.iter_mut().zip(bytes.iter()) {
201            *this ^= *that;
202        }
203    }
204
205    unsafe {
206        // The use of a mutable pointer to `session_secrand`, which is a local variable,
207        // may seem concerning/wrong. It is ok: this pointer is only mutable because the
208        // behavior of `secp256k1_musig_nonce_gen` on error is to zero out the secret
209        // nonce. We guarantee this won't happen, but also if it does, it's harmless
210        // to zero out a local variable without propagating that change back to the
211        // caller or anything.
212        let mut sec_nonce = MaybeUninit::<ffi::MusigSecNonce>::uninit();
213        let mut pub_nonce = MaybeUninit::<ffi::MusigPubNonce>::uninit();
214
215        let ret = crate::with_global_context(
216            |secp: &Secp256k1<crate::AllPreallocated>| {
217                ffi::secp256k1_musig_nonce_gen(
218                    secp.ctx.as_ptr(),
219                    sec_nonce.as_mut_ptr(),
220                    pub_nonce.as_mut_ptr(),
221                    session_secrand.as_mut_ptr(),
222                    sk_ptr,
223                    pub_key.as_c_ptr(),
224                    msg_ptr,
225                    cache_ptr,
226                    extra_ptr,
227                )
228            },
229            Some(&seed),
230        );
231
232        if ret == 0 {
233            // Rust type system guarantees that
234            // - input secret key is valid
235            // - msg is 32 bytes
236            // - Key agg cache is valid
237            // - extra input is 32 bytes
238            // This can only happen when the session id is all zeros
239            panic!("A zero session id was supplied")
240        } else {
241            let pub_nonce = PublicNonce(pub_nonce.assume_init());
242            let sec_nonce = SecretNonce(sec_nonce.assume_init());
243            (sec_nonce, pub_nonce)
244        }
245    }
246}
247
248/// A Musig partial signature.
249#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
250#[repr(transparent)]
251pub struct PartialSignature(ffi::MusigPartialSignature);
252
253impl CPtr for PartialSignature {
254    type Target = ffi::MusigPartialSignature;
255
256    fn as_c_ptr(&self) -> *const Self::Target { self.as_ptr() }
257
258    fn as_mut_c_ptr(&mut self) -> *mut Self::Target { self.as_mut_ptr() }
259}
260
261impl fmt::LowerHex for PartialSignature {
262    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
263        for b in self.serialize() {
264            write!(f, "{:02x}", b)?;
265        }
266        Ok(())
267    }
268}
269
270impl fmt::Display for PartialSignature {
271    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
272}
273
274impl core::str::FromStr for PartialSignature {
275    type Err = ParseError;
276    fn from_str(s: &str) -> Result<Self, Self::Err> {
277        let mut res = [0u8; PART_SIG_SERIALIZED_SIZE];
278        match from_hex(s, &mut res) {
279            Ok(PART_SIG_SERIALIZED_SIZE) => PartialSignature::from_byte_array(&res),
280            _ => Err(ParseError::MalformedArg),
281        }
282    }
283}
284
285#[cfg(feature = "serde")]
286impl serde::Serialize for PartialSignature {
287    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
288        if s.is_human_readable() {
289            s.collect_str(self)
290        } else {
291            s.serialize_bytes(&self.serialize()[..])
292        }
293    }
294}
295
296#[cfg(feature = "serde")]
297impl<'de> serde::Deserialize<'de> for PartialSignature {
298    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
299        if d.is_human_readable() {
300            d.deserialize_str(super::serde_util::FromStrVisitor::new(
301                "a hex string representing a MuSig2 partial signature",
302            ))
303        } else {
304            d.deserialize_bytes(super::serde_util::BytesVisitor::new(
305                "a raw MuSig2 partial signature",
306                |slice| {
307                    let bytes: &[u8; PART_SIG_SERIALIZED_SIZE] =
308                        slice.try_into().map_err(|_| ParseError::MalformedArg)?;
309
310                    Self::from_byte_array(bytes)
311                },
312            ))
313        }
314    }
315}
316
317impl PartialSignature {
318    /// Serialize a PartialSignature as a byte array.
319    pub fn serialize(&self) -> [u8; PART_SIG_SERIALIZED_SIZE] {
320        let mut data = MaybeUninit::<[u8; PART_SIG_SERIALIZED_SIZE]>::uninit();
321        unsafe {
322            if ffi::secp256k1_musig_partial_sig_serialize(
323                ffi::secp256k1_context_no_precomp,
324                data.as_mut_ptr() as *mut u8,
325                self.as_ptr(),
326            ) == 0
327            {
328                // Only fails if args are null pointer which is possible in safe rust
329                unreachable!("Serialization cannot fail")
330            } else {
331                data.assume_init()
332            }
333        }
334    }
335
336    /// Deserialize a PartialSignature from bytes.
337    ///
338    /// # Errors:
339    ///
340    /// - MalformedArg: If the signature [`PartialSignature`] is out of curve order
341    pub fn from_byte_array(data: &[u8; PART_SIG_SERIALIZED_SIZE]) -> Result<Self, ParseError> {
342        let mut partial_sig = MaybeUninit::<ffi::MusigPartialSignature>::uninit();
343        unsafe {
344            if ffi::secp256k1_musig_partial_sig_parse(
345                ffi::secp256k1_context_no_precomp,
346                partial_sig.as_mut_ptr(),
347                data.as_ptr(),
348            ) == 0
349            {
350                Err(ParseError::MalformedArg)
351            } else {
352                Ok(PartialSignature(partial_sig.assume_init()))
353            }
354        }
355    }
356
357    /// Get a const pointer to the inner PartialSignature
358    pub fn as_ptr(&self) -> *const ffi::MusigPartialSignature { &self.0 }
359
360    /// Get a mut pointer to the inner PartialSignature
361    pub fn as_mut_ptr(&mut self) -> *mut ffi::MusigPartialSignature { &mut self.0 }
362}
363
364impl KeyAggCache {
365    /// Creates a new [`KeyAggCache`] by supplying a list of PublicKeys used in the session.
366    ///
367    /// Computes a combined public key and the hash of the given public keys.
368    ///
369    /// Different orders of `pubkeys` result in different `agg_pk`s.
370    /// The pubkeys can be sorted lexicographically before combining with which
371    /// ensures the same resulting `agg_pk` for the same multiset of pubkeys.
372    /// This is useful to do before aggregating pubkeys, such that the order of pubkeys
373    /// does not affect the combined public key.
374    /// To do this, call [`key::sort_pubkeys`].
375    ///
376    /// # Returns
377    ///
378    ///  A [`KeyAggCache`] the can be used [`KeyAggCache::nonce_gen`] and [`Session::new`].
379    ///
380    /// # Args:
381    ///
382    /// * `secp` - Secp256k1 context object initialized for verification
383    /// * `pubkeys` - Input array of public keys to combine. The order is important; a
384    ///   different order will result in a different combined public key
385    ///
386    /// Example:
387    ///
388    /// ```rust
389    /// # #[cfg(feature = "std")]
390    /// # #[cfg(feature = "rand")] {
391    /// # use secp256k1::{SecretKey, Keypair, PublicKey};
392    /// # use secp256k1::musig::KeyAggCache;
393    /// # let sk1 = SecretKey::new(&mut rand::rng());
394    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
395    /// # let sk2 = SecretKey::new(&mut rand::rng());
396    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
397    /// #
398    /// let key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
399    /// let _agg_pk = key_agg_cache.agg_pk();
400    /// # }
401    /// ```
402    ///
403    /// # Panics
404    ///
405    /// Panics if an empty slice of pubkeys is provided.
406    pub fn new(pubkeys: &[&PublicKey]) -> Self {
407        if pubkeys.is_empty() {
408            panic!("Cannot aggregate an empty slice of pubkeys");
409        }
410
411        let mut key_agg_cache = MaybeUninit::<ffi::MusigKeyAggCache>::uninit();
412        let mut agg_pk = MaybeUninit::<ffi::XOnlyPublicKey>::uninit();
413
414        unsafe {
415            let pubkeys_ref = core::slice::from_raw_parts(
416                pubkeys.as_c_ptr() as *const *const ffi::PublicKey,
417                pubkeys.len(),
418            );
419
420            let ret = crate::with_global_context(
421                |secp: &Secp256k1<crate::AllPreallocated>| {
422                    ffi::secp256k1_musig_pubkey_agg(
423                        secp.ctx.as_ptr(),
424                        agg_pk.as_mut_ptr(),
425                        key_agg_cache.as_mut_ptr(),
426                        pubkeys_ref.as_ptr(),
427                        pubkeys_ref.len(),
428                    )
429                },
430                None,
431            );
432            if ret == 0 {
433                // Returns 0 only if the keys are malformed that never happens in safe rust type system.
434                unreachable!("Invalid XOnlyPublicKey in input pubkeys")
435            } else {
436                // secp256k1_musig_pubkey_agg overwrites the cache and the key so this is sound.
437                let key_agg_cache = key_agg_cache.assume_init();
438                let agg_pk = XOnlyPublicKey::from(agg_pk.assume_init());
439                KeyAggCache { data: key_agg_cache, aggregated_xonly_public_key: agg_pk }
440            }
441        }
442    }
443
444    /// Obtains the aggregate public key for this [`KeyAggCache`]
445    pub fn agg_pk(&self) -> XOnlyPublicKey { self.aggregated_xonly_public_key }
446
447    /// Obtains the aggregate public key for this [`KeyAggCache`] as a full [`PublicKey`].
448    ///
449    /// This is only useful if you need the non-xonly public key, in particular for
450    /// plain (non-xonly) tweaking or batch-verifying multiple key aggregations
451    /// (not supported yet).
452    pub fn agg_pk_full(&self) -> PublicKey {
453        unsafe {
454            let mut pk = PublicKey::from(ffi::PublicKey::new());
455            if ffi::secp256k1_musig_pubkey_get(
456                ffi::secp256k1_context_no_precomp,
457                pk.as_mut_c_ptr(),
458                self.as_ptr(),
459            ) == 0
460            {
461                // Returns 0 only if the keys are malformed that never happens in safe rust type system.
462                unreachable!("All the arguments are valid")
463            } else {
464                pk
465            }
466        }
467    }
468
469    /// Apply ordinary "EC" tweaking to a public key in a [`KeyAggCache`].
470    ///
471    /// This is done by adding the generator multiplied with `tweak32` to it. Returns the tweaked [`PublicKey`].
472    /// This is useful for deriving child keys from an aggregate public key via BIP32.
473    /// This function is required if you want to _sign_ for a tweaked aggregate key.
474    ///
475    /// # Arguments:
476    ///
477    /// * `secp` : [`Secp256k1`] context object initialized for verification
478    /// * `tweak`: tweak of type [`Scalar`] with which to tweak the aggregated key
479    ///
480    /// # Errors:
481    ///
482    /// If resulting public key would be invalid (only when the tweak is the negation of the corresponding
483    /// secret key). For uniformly random 32-byte arrays(for example, in BIP 32 derivation) the chance of
484    /// being invalid is negligible (around 1 in 2^128).
485    ///
486    /// Example:
487    ///
488    /// ```rust
489    /// # #[cfg(not(secp256k1_fuzz))]
490    /// # #[cfg(feature = "std")]
491    /// # #[cfg(feature = "rand")] {
492    /// # use secp256k1::{Scalar, SecretKey, Keypair, PublicKey};
493    /// # use secp256k1::musig::KeyAggCache;
494    /// # let sk1 = SecretKey::new(&mut rand::rng());
495    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
496    /// # let sk2 = SecretKey::new(&mut rand::rng());
497    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
498    /// #
499    /// let mut key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
500    ///
501    /// let tweak: [u8; 32] = *b"this could be a BIP32 tweak....\0";
502    /// let tweak = Scalar::from_be_bytes(tweak).unwrap();
503    /// let tweaked_key = key_agg_cache.pubkey_ec_tweak_add(&tweak).unwrap();
504    /// # }
505    /// ```
506    pub fn pubkey_ec_tweak_add(&mut self, tweak: &Scalar) -> Result<PublicKey, InvalidTweakErr> {
507        unsafe {
508            let mut out = PublicKey::from(ffi::PublicKey::new());
509
510            let ret = crate::with_global_context(
511                |secp: &Secp256k1<crate::AllPreallocated>| {
512                    ffi::secp256k1_musig_pubkey_ec_tweak_add(
513                        secp.ctx.as_ptr(),
514                        out.as_mut_c_ptr(),
515                        self.as_mut_ptr(),
516                        tweak.as_c_ptr(),
517                    )
518                },
519                None,
520            );
521            if ret == 0 {
522                Err(InvalidTweakErr)
523            } else {
524                self.aggregated_xonly_public_key = out.x_only_public_key().0;
525                Ok(out)
526            }
527        }
528    }
529
530    /// Apply "x-only" tweaking to a public key in a [`KeyAggCache`].
531    ///
532    /// This is done by adding the generator multiplied with `tweak32` to it. Returns the tweaked [`XOnlyPublicKey`].
533    /// This is useful in creating taproot outputs.
534    /// This function is required if you want to _sign_ for a tweaked aggregate key.
535    ///
536    /// # Arguments:
537    ///
538    /// * `secp` : [`Secp256k1`] context object initialized for verification
539    /// * `tweak`: tweak of type [`SecretKey`] with which to tweak the aggregated key
540    ///
541    /// # Errors:
542    ///
543    /// If resulting public key would be invalid (only when the tweak is the negation of the corresponding
544    /// secret key). For uniformly random 32-byte arrays(for example, in BIP341 taproot tweaks) the chance of
545    /// being invalid is negligible (around 1 in 2^128)
546    ///
547    /// Example:
548    ///
549    /// ```rust
550    /// # #[cfg(not(secp256k1_fuzz))]
551    /// # #[cfg(feature = "std")]
552    /// # #[cfg(feature = "rand")] {
553    /// # use secp256k1::{Scalar, SecretKey, Keypair, PublicKey};
554    /// # use secp256k1::musig::KeyAggCache;
555    /// # let sk1 = SecretKey::new(&mut rand::rng());
556    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
557    /// # let sk2 = SecretKey::new(&mut rand::rng());
558    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
559    ///
560    /// let mut key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
561    ///
562    /// let tweak = Scalar::from_be_bytes(*b"Insecure tweak, Don't use this!!").unwrap(); // tweak could be from tap
563    /// let _x_only_key_tweaked = key_agg_cache.pubkey_xonly_tweak_add(&tweak).unwrap();
564    /// # }
565    /// ```
566    pub fn pubkey_xonly_tweak_add(&mut self, tweak: &Scalar) -> Result<PublicKey, InvalidTweakErr> {
567        unsafe {
568            let mut out = PublicKey::from(ffi::PublicKey::new());
569
570            let ret = crate::with_global_context(
571                |secp: &Secp256k1<crate::AllPreallocated>| {
572                    ffi::secp256k1_musig_pubkey_xonly_tweak_add(
573                        secp.ctx.as_ptr(),
574                        out.as_mut_c_ptr(),
575                        self.as_mut_ptr(),
576                        tweak.as_c_ptr(),
577                    )
578                },
579                None,
580            );
581            if ret == 0 {
582                Err(InvalidTweakErr)
583            } else {
584                self.aggregated_xonly_public_key = out.x_only_public_key().0;
585                Ok(out)
586            }
587        }
588    }
589
590    /// Starts a signing session by generating a nonce
591    ///
592    /// This function outputs a secret nonce that will be required for signing and a
593    /// corresponding public nonce that is intended to be sent to other signers.
594    ///
595    /// MuSig differs from regular Schnorr signing in that implementers _must_ take
596    /// special care to not reuse a nonce. If you cannot provide a `sec_key`, `session_secrand`
597    /// UNIFORMLY RANDOM AND KEPT SECRET (even from other signers).
598    /// Refer to libsecp256k1 documentation for additional considerations.
599    ///
600    /// MuSig2 nonces can be precomputed without knowing the aggregate public key, the message to sign.
601    /// See the `new_nonce_pair` method that allows generating [`SecretNonce`] and [`PublicNonce`]
602    /// with only the `session_secrand` field.
603    ///
604    /// If the aggregator lies, the resulting signature will simply be invalid.
605    ///
606    /// Remember that nonce reuse will immediately leak the secret key!
607    ///
608    /// # Returns:
609    ///
610    /// A pair of ([`SecretNonce`], [`PublicNonce`]) that can be later used signing and aggregation
611    ///
612    /// # Arguments:
613    ///
614    /// * `secp` : [`Secp256k1`] context object initialized for signing
615    /// * `session_secrand`: [`SessionSecretRand`] Uniform random identifier for this session. Each call to this
616    ///   function must have a UNIQUE `session_secrand`.
617    /// * `pub_key`: [`PublicKey`] of the signer creating the nonce.
618    /// * `msg`: message that will be signed later on.
619    /// * `extra_rand`: Additional randomness for mis-use resistance
620    ///
621    /// Example:
622    ///
623    /// ```rust
624    /// # #[cfg(feature = "std")]
625    /// # #[cfg(feature = "rand")] {
626    /// # use secp256k1::{SecretKey, Keypair, PublicKey};
627    /// # use secp256k1::musig::{KeyAggCache, SessionSecretRand};
628    /// # let sk1 = SecretKey::new(&mut rand::rng());
629    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
630    /// # let sk2 = SecretKey::new(&mut rand::rng());
631    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
632    /// #
633    /// let key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
634    /// // The session id must be sampled at random. Read documentation for more details.
635    /// let session_secrand = SessionSecretRand::from_rng(&mut rand::rng());
636    ///
637    /// // Provide the current time for mis-use resistance
638    /// let msg = b"Public message we want to sign!!";
639    /// let extra_rand : Option<[u8; 32]> = None;
640    /// let (_sec_nonce, _pub_nonce) = key_agg_cache.nonce_gen(session_secrand, pub_key1, msg, extra_rand);
641    /// # }
642    /// ```
643    pub fn nonce_gen(
644        &self,
645        session_secrand: SessionSecretRand,
646        pub_key: PublicKey,
647        msg: &[u8; 32],
648        extra_rand: Option<[u8; 32]>,
649    ) -> (SecretNonce, PublicNonce) {
650        // The secret key here is supplied as NULL. This is okay because we supply the
651        // public key and the message.
652        // This makes a simple API for the user because it does not require them to pass here.
653        new_nonce_pair(session_secrand, Some(self), None, pub_key, Some(msg), extra_rand)
654    }
655
656    /// Get a const pointer to the inner KeyAggCache
657    pub fn as_ptr(&self) -> *const ffi::MusigKeyAggCache { &self.data }
658
659    /// Get a mut pointer to the inner KeyAggCache
660    pub fn as_mut_ptr(&mut self) -> *mut ffi::MusigKeyAggCache { &mut self.data }
661}
662
663/// Musig Secret Nonce.
664///
665/// A signer who is online throughout the whole process and can keep this structure
666/// in memory can use the provided API functions for a safe standard workflow.
667///
668/// This structure does not implement `Copy` or `Clone`; after construction the only
669/// thing that can or should be done with this nonce is to call [`Session::partial_sign`],
670/// which will take ownership. This is to prevent accidental reuse of the nonce.
671///
672/// See the warnings on [`Self::dangerous_into_bytes`] for more information about
673/// the risks of non-standard workflows.
674#[allow(missing_copy_implementations)]
675#[derive(Debug)]
676pub struct SecretNonce(ffi::MusigSecNonce);
677
678impl CPtr for SecretNonce {
679    type Target = ffi::MusigSecNonce;
680
681    fn as_c_ptr(&self) -> *const Self::Target { self.as_ptr() }
682
683    fn as_mut_c_ptr(&mut self) -> *mut Self::Target { self.as_mut_ptr() }
684}
685
686impl SecretNonce {
687    /// Get a const pointer to the inner KeyAggCache
688    pub fn as_ptr(&self) -> *const ffi::MusigSecNonce { &self.0 }
689
690    /// Get a mut pointer to the inner KeyAggCache
691    pub fn as_mut_ptr(&mut self) -> *mut ffi::MusigSecNonce { &mut self.0 }
692
693    /// Function to return a copy of the internal array. See WARNING before using this function.
694    ///
695    /// # Warning:
696    ///
697    /// Storing and re-creating this structure may lead to nonce reuse, which will leak
698    /// your secret key in two signing sessions, even if neither session is completed.
699    /// These functions should be avoided if possible and used with care.
700    ///
701    /// See <https://blockstream.com/2019/02/18/musig-a-new-multisignature-standard/>
702    /// for more details about these risks.
703    ///
704    /// # Warning:
705    ///
706    /// The underlying library, libsecp256k1, does not guarantee the byte format will be consistent
707    /// across versions or platforms. Special care should be taken to ensure the returned bytes are
708    /// only ever passed to `dangerous_from_bytes` from the same libsecp256k1 version, and the same
709    /// platform.
710    pub fn dangerous_into_bytes(self) -> [u8; secp256k1_sys::MUSIG_SECNONCE_SIZE] {
711        self.0.dangerous_into_bytes()
712    }
713
714    /// Function to create a new [`SecretNonce`] from a 32 byte array.
715    ///
716    /// Refer to the warnings on [`SecretNonce::dangerous_into_bytes`] for more details.
717    pub fn dangerous_from_bytes(array: [u8; secp256k1_sys::MUSIG_SECNONCE_SIZE]) -> Self {
718        SecretNonce(ffi::MusigSecNonce::dangerous_from_bytes(array))
719    }
720}
721
722/// An individual MuSig public nonce. Not to be confused with [`AggregatedNonce`].
723#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
724#[repr(transparent)]
725pub struct PublicNonce(ffi::MusigPubNonce);
726
727impl CPtr for PublicNonce {
728    type Target = ffi::MusigPubNonce;
729
730    fn as_c_ptr(&self) -> *const Self::Target { self.as_ptr() }
731
732    fn as_mut_c_ptr(&mut self) -> *mut Self::Target { self.as_mut_ptr() }
733}
734
735impl fmt::LowerHex for PublicNonce {
736    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
737        for b in self.serialize() {
738            write!(f, "{:02x}", b)?;
739        }
740        Ok(())
741    }
742}
743
744impl fmt::Display for PublicNonce {
745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
746}
747
748impl core::str::FromStr for PublicNonce {
749    type Err = ParseError;
750    fn from_str(s: &str) -> Result<Self, Self::Err> {
751        let mut res = [0u8; PUBNONCE_SERIALIZED_SIZE];
752        match from_hex(s, &mut res) {
753            Ok(PUBNONCE_SERIALIZED_SIZE) => PublicNonce::from_byte_array(&res),
754            _ => Err(ParseError::MalformedArg),
755        }
756    }
757}
758
759#[cfg(feature = "serde")]
760impl serde::Serialize for PublicNonce {
761    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
762        if s.is_human_readable() {
763            s.collect_str(self)
764        } else {
765            s.serialize_bytes(&self.serialize()[..])
766        }
767    }
768}
769
770#[cfg(feature = "serde")]
771impl<'de> serde::Deserialize<'de> for PublicNonce {
772    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
773        if d.is_human_readable() {
774            d.deserialize_str(super::serde_util::FromStrVisitor::new(
775                "a hex string representing a MuSig2 public nonce",
776            ))
777        } else {
778            d.deserialize_bytes(super::serde_util::BytesVisitor::new(
779                "a raw MuSig2 public nonce",
780                |slice| {
781                    let bytes: &[u8; PUBNONCE_SERIALIZED_SIZE] =
782                        slice.try_into().map_err(|_| ParseError::MalformedArg)?;
783
784                    Self::from_byte_array(bytes)
785                },
786            ))
787        }
788    }
789}
790
791impl PublicNonce {
792    /// Serialize a PublicNonce
793    pub fn serialize(&self) -> [u8; PUBNONCE_SERIALIZED_SIZE] {
794        let mut data = [0; PUBNONCE_SERIALIZED_SIZE];
795        unsafe {
796            if ffi::secp256k1_musig_pubnonce_serialize(
797                ffi::secp256k1_context_no_precomp,
798                data.as_mut_ptr(),
799                self.as_ptr(),
800            ) == 0
801            {
802                // Only fails when the arguments are invalid which is not possible in safe rust
803                unreachable!("Arguments must be valid and well-typed")
804            } else {
805                data
806            }
807        }
808    }
809
810    /// Deserialize a PublicNonce from a portable byte representation
811    ///
812    /// # Errors:
813    ///
814    /// - MalformedArg: If the [`PublicNonce`] is 132 bytes, but out of curve order
815    pub fn from_byte_array(data: &[u8; PUBNONCE_SERIALIZED_SIZE]) -> Result<Self, ParseError> {
816        let mut pub_nonce = MaybeUninit::<ffi::MusigPubNonce>::uninit();
817        unsafe {
818            if ffi::secp256k1_musig_pubnonce_parse(
819                ffi::secp256k1_context_no_precomp,
820                pub_nonce.as_mut_ptr(),
821                data.as_ptr(),
822            ) == 0
823            {
824                Err(ParseError::MalformedArg)
825            } else {
826                Ok(PublicNonce(pub_nonce.assume_init()))
827            }
828        }
829    }
830
831    /// Get a const pointer to the inner PublicNonce
832    pub fn as_ptr(&self) -> *const ffi::MusigPubNonce { &self.0 }
833
834    /// Get a mut pointer to the inner PublicNonce
835    pub fn as_mut_ptr(&mut self) -> *mut ffi::MusigPubNonce { &mut self.0 }
836}
837
838/// Musig aggregated nonce computed by aggregating all individual public nonces
839#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
840pub struct AggregatedNonce(ffi::MusigAggNonce);
841
842impl CPtr for AggregatedNonce {
843    type Target = ffi::MusigAggNonce;
844
845    fn as_c_ptr(&self) -> *const Self::Target { self.as_ptr() }
846
847    fn as_mut_c_ptr(&mut self) -> *mut Self::Target { self.as_mut_ptr() }
848}
849
850impl fmt::LowerHex for AggregatedNonce {
851    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
852        for b in self.serialize() {
853            write!(f, "{:02x}", b)?;
854        }
855        Ok(())
856    }
857}
858
859impl fmt::Display for AggregatedNonce {
860    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
861}
862
863impl core::str::FromStr for AggregatedNonce {
864    type Err = ParseError;
865    fn from_str(s: &str) -> Result<Self, Self::Err> {
866        let mut res = [0u8; AGGNONCE_SERIALIZED_SIZE];
867        match from_hex(s, &mut res) {
868            Ok(AGGNONCE_SERIALIZED_SIZE) => AggregatedNonce::from_byte_array(&res),
869            _ => Err(ParseError::MalformedArg),
870        }
871    }
872}
873
874#[cfg(feature = "serde")]
875impl serde::Serialize for AggregatedNonce {
876    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
877        if s.is_human_readable() {
878            s.collect_str(self)
879        } else {
880            s.serialize_bytes(&self.serialize()[..])
881        }
882    }
883}
884
885#[cfg(feature = "serde")]
886impl<'de> serde::Deserialize<'de> for AggregatedNonce {
887    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
888        if d.is_human_readable() {
889            d.deserialize_str(super::serde_util::FromStrVisitor::new(
890                "a hex string representing a MuSig2 aggregated nonce",
891            ))
892        } else {
893            d.deserialize_bytes(super::serde_util::BytesVisitor::new(
894                "a raw MuSig2 aggregated nonce",
895                |slice| {
896                    let bytes: &[u8; AGGNONCE_SERIALIZED_SIZE] =
897                        slice.try_into().map_err(|_| ParseError::MalformedArg)?;
898
899                    Self::from_byte_array(bytes)
900                },
901            ))
902        }
903    }
904}
905
906impl AggregatedNonce {
907    /// Combine received public nonces into a single aggregated nonce
908    ///
909    /// This is useful to reduce the communication between signers, because instead
910    /// of everyone sending nonces to everyone else, there can be one party
911    /// receiving all nonces, combining the nonces with this function and then
912    /// sending only the combined nonce back to the signers.
913    ///
914    /// Example:
915    ///
916    /// ```rust
917    /// # #[cfg(feature = "std")]
918    /// # #[cfg(feature = "rand")] {
919    /// # use secp256k1::{SecretKey, Keypair, PublicKey};
920    /// # use secp256k1::musig::{AggregatedNonce, KeyAggCache, SessionSecretRand};
921    /// # let sk1 = SecretKey::new(&mut rand::rng());
922    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
923    /// # let sk2 = SecretKey::new(&mut rand::rng());
924    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
925    ///
926    /// # let key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
927    /// // The session id must be sampled at random. Read documentation for more details.
928    ///
929    /// let msg = b"Public message we want to sign!!";
930    ///
931    /// let session_secrand1 = SessionSecretRand::from_rng(&mut rand::rng());
932    /// let (_sec_nonce1, pub_nonce1) = key_agg_cache.nonce_gen(session_secrand1, pub_key1, msg, None);
933    ///
934    /// // Signer two does the same: Possibly on a different device
935    /// let session_secrand2 = SessionSecretRand::from_rng(&mut rand::rng());
936    /// let (_sec_nonce2, pub_nonce2) = key_agg_cache.nonce_gen(session_secrand2, pub_key2, msg, None);
937    ///
938    /// let aggnonce = AggregatedNonce::new(&[&pub_nonce1, &pub_nonce2]);
939    /// # }
940    /// ```
941    /// # Panics
942    ///
943    /// Panics if an empty slice of nonces is provided.
944    ///
945    pub fn new(nonces: &[&PublicNonce]) -> Self {
946        if nonces.is_empty() {
947            panic!("Cannot aggregate an empty slice of nonces");
948        }
949
950        let mut aggnonce = MaybeUninit::<ffi::MusigAggNonce>::uninit();
951
952        unsafe {
953            let pubnonces = core::slice::from_raw_parts(
954                nonces.as_c_ptr() as *const *const ffi::MusigPubNonce,
955                nonces.len(),
956            );
957
958            let ret = crate::with_global_context(
959                |secp: &Secp256k1<crate::AllPreallocated>| {
960                    ffi::secp256k1_musig_nonce_agg(
961                        secp.ctx().as_ptr(),
962                        aggnonce.as_mut_ptr(),
963                        pubnonces.as_ptr(),
964                        pubnonces.len(),
965                    )
966                },
967                None,
968            );
969            if ret == 0 {
970                // This can only crash if the individual nonces are invalid which is not possible is rust.
971                // Note that even if aggregate nonce is point at infinity, the musig spec sets it as `G`
972                unreachable!("Public key nonces are well-formed and valid in rust typesystem")
973            } else {
974                AggregatedNonce(aggnonce.assume_init())
975            }
976        }
977    }
978
979    /// Serialize a AggregatedNonce into a 66 bytes array.
980    pub fn serialize(&self) -> [u8; AGGNONCE_SERIALIZED_SIZE] {
981        let mut data = [0; AGGNONCE_SERIALIZED_SIZE];
982        unsafe {
983            if ffi::secp256k1_musig_aggnonce_serialize(
984                ffi::secp256k1_context_no_precomp,
985                data.as_mut_ptr(),
986                self.as_ptr(),
987            ) == 0
988            {
989                // Only fails when the arguments are invalid which is not possible in safe rust
990                unreachable!("Arguments must be valid and well-typed")
991            } else {
992                data
993            }
994        }
995    }
996
997    /// Deserialize a AggregatedNonce from byte slice
998    ///
999    /// # Errors:
1000    ///
1001    /// - MalformedArg: If the byte slice is 66 bytes, but the [`AggregatedNonce`] is invalid
1002    pub fn from_byte_array(data: &[u8; AGGNONCE_SERIALIZED_SIZE]) -> Result<Self, ParseError> {
1003        let mut aggnonce = MaybeUninit::<ffi::MusigAggNonce>::uninit();
1004        unsafe {
1005            if ffi::secp256k1_musig_aggnonce_parse(
1006                ffi::secp256k1_context_no_precomp,
1007                aggnonce.as_mut_ptr(),
1008                data.as_ptr(),
1009            ) == 0
1010            {
1011                Err(ParseError::MalformedArg)
1012            } else {
1013                Ok(AggregatedNonce(aggnonce.assume_init()))
1014            }
1015        }
1016    }
1017
1018    /// Get a const pointer to the inner AggregatedNonce
1019    pub fn as_ptr(&self) -> *const ffi::MusigAggNonce { &self.0 }
1020
1021    /// Get a mut pointer to the inner AggregatedNonce
1022    pub fn as_mut_ptr(&mut self) -> *mut ffi::MusigAggNonce { &mut self.0 }
1023}
1024
1025/// The aggregated signature of all partial signatures.
1026#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1027pub struct AggregatedSignature([u8; 64]);
1028
1029impl AggregatedSignature {
1030    /// Returns the aggregated signature [`schnorr::Signature`] assuming it is valid.
1031    ///
1032    /// The `partial_sig_agg` function cannot guarantee that the produced signature is valid because participants
1033    /// may send invalid signatures. In some applications this doesn't matter because the invalid message is simply
1034    /// dropped with no consequences. These can simply call this function to obtain the resulting signature. However
1035    /// in applications that require having valid signatures before continuing (e.g. presigned transactions in Bitcoin Lightning Network) this would be exploitable. Such applications MUST verify the resulting signature using the
1036    /// [`verify`](Self::verify) method.
1037    ///
1038    /// Note that while an alternative approach of verifying partial signatures is valid, verifying the aggregated
1039    /// signature is more performant. Thus it should be generally better to verify the signature using this function first
1040    /// and fall back to detection of violators if it fails.
1041    pub fn assume_valid(self) -> schnorr::Signature { schnorr::Signature::from_byte_array(self.0) }
1042
1043    /// Verify the aggregated signature against the aggregate public key and message
1044    /// before returning the signature.
1045    pub fn verify(
1046        self,
1047        aggregate_key: &XOnlyPublicKey,
1048        message: &[u8],
1049    ) -> Result<schnorr::Signature, Error> {
1050        let sig = schnorr::Signature::from_byte_array(self.0);
1051        schnorr::verify(&sig, message, aggregate_key)
1052            .map(|_| sig)
1053            .map_err(|_| Error::IncorrectSignature)
1054    }
1055}
1056
1057/// A musig Signing session.
1058#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1059pub struct Session(ffi::MusigSession);
1060
1061impl Session {
1062    /// Creates a new musig signing session.
1063    ///
1064    /// Takes the public nonces of all signers and computes a session that is
1065    /// required for signing and verification of partial signatures.
1066    ///
1067    /// # Returns:
1068    ///
1069    /// A [`Session`] that can be later used for signing.
1070    ///
1071    /// # Arguments:
1072    ///
1073    /// * `secp` : [`Secp256k1`] context object initialized for signing
1074    /// * `key_agg_cache`: [`KeyAggCache`] to be used for this session
1075    /// * `agg_nonce`: [`AggregatedNonce`], the aggregate nonce
1076    /// * `msg`: message that will be signed later on.
1077    ///
1078    /// Example:
1079    ///
1080    /// ```rust
1081    /// # #[cfg(feature = "std")]
1082    /// # #[cfg(feature = "rand")] {
1083    /// # use secp256k1::{SecretKey, Keypair, PublicKey};
1084    /// # use secp256k1::musig::{AggregatedNonce, KeyAggCache, Session, SessionSecretRand};
1085    /// # let sk1 = SecretKey::new(&mut rand::rng());
1086    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
1087    /// # let sk2 = SecretKey::new(&mut rand::rng());
1088    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
1089    ///
1090    /// # let key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
1091    /// // The session id must be sampled at random. Read documentation for more details.
1092    ///
1093    /// let msg = b"Public message we want to sign!!";
1094    ///
1095    /// // Provide the current time for mis-use resistance
1096    /// let session_secrand1 = SessionSecretRand::from_rng(&mut rand::rng());
1097    /// let extra_rand1 : Option<[u8; 32]> = None;
1098    /// let (_sec_nonce1, pub_nonce1) = key_agg_cache.nonce_gen(session_secrand1, pub_key1, msg, extra_rand1);
1099    ///
1100    /// // Signer two does the same. Possibly on a different device
1101    /// let session_secrand2 = SessionSecretRand::from_rng(&mut rand::rng());
1102    /// let extra_rand2 : Option<[u8; 32]> = None;
1103    /// let (_sec_nonce2, pub_nonce2) = key_agg_cache.nonce_gen(session_secrand2, pub_key2, msg, extra_rand2);
1104    ///
1105    /// let aggnonce = AggregatedNonce::new(&[&pub_nonce1, &pub_nonce2]);
1106    ///
1107    /// let session = Session::new(
1108    ///     &key_agg_cache,
1109    ///     aggnonce,
1110    ///     msg,
1111    /// );
1112    /// # }
1113    /// ```
1114    pub fn new(key_agg_cache: &KeyAggCache, agg_nonce: AggregatedNonce, msg: &[u8; 32]) -> Self {
1115        let mut session = MaybeUninit::<ffi::MusigSession>::uninit();
1116
1117        unsafe {
1118            let ret = crate::with_global_context(
1119                |secp: &Secp256k1<crate::AllPreallocated>| {
1120                    ffi::secp256k1_musig_nonce_process(
1121                        secp.ctx().as_ptr(),
1122                        session.as_mut_ptr(),
1123                        agg_nonce.as_ptr(),
1124                        msg.as_c_ptr(),
1125                        key_agg_cache.as_ptr(),
1126                    )
1127                },
1128                None,
1129            );
1130            if ret == 0 {
1131                // Only fails on cryptographically unreachable codes or if the args are invalid.
1132                // None of which can occur in safe rust.
1133                unreachable!("Impossible to construct invalid arguments in safe rust.
1134                    Also reaches here if R1 + R2*b == point at infinity, but only occurs with 2^128 probability")
1135            } else {
1136                Session(session.assume_init())
1137            }
1138        }
1139    }
1140
1141    /// Produces a partial signature for a given key pair and secret nonce.
1142    ///
1143    /// Remember that nonce reuse will immediately leak the secret key!
1144    ///
1145    /// # Returns:
1146    ///
1147    /// A [`PartialSignature`] that can be later be aggregated into a [`schnorr::Signature`]
1148    ///
1149    /// # Arguments:
1150    ///
1151    /// * `secp` : [`Secp256k1`] context object initialized for signing
1152    /// * `sec_nonce`: [`SecretNonce`] to be used for this session that has never
1153    ///   been used before. For mis-use resistance, this API takes a mutable reference
1154    ///   to `sec_nonce` and sets it to zero even if the partial signing fails.
1155    /// * `key_pair`: The [`Keypair`] to sign the message
1156    /// * `key_agg_cache`: [`KeyAggCache`] containing the aggregate pubkey used in
1157    ///   the creation of this session
1158    ///
1159    /// # Errors:
1160    ///
1161    /// - If the provided [`SecretNonce`] has already been used for signing
1162    ///
1163    pub fn partial_sign(
1164        &self,
1165        mut secnonce: SecretNonce,
1166        keypair: &Keypair,
1167        key_agg_cache: &KeyAggCache,
1168    ) -> PartialSignature {
1169        unsafe {
1170            let mut partial_sig = MaybeUninit::<ffi::MusigPartialSignature>::uninit();
1171
1172            let res = crate::with_global_context(
1173                |secp: &Secp256k1<crate::AllPreallocated>| {
1174                    ffi::secp256k1_musig_partial_sign(
1175                        secp.ctx().as_ptr(),
1176                        partial_sig.as_mut_ptr(),
1177                        secnonce.as_mut_ptr(),
1178                        keypair.as_c_ptr(),
1179                        key_agg_cache.as_ptr(),
1180                        self.as_ptr(),
1181                    )
1182                },
1183                Some(&keypair.secret_bytes()),
1184            );
1185
1186            assert_eq!(res, 1);
1187            PartialSignature(partial_sig.assume_init())
1188        }
1189    }
1190
1191    /// Checks that an individual partial signature verifies
1192    ///
1193    /// This function is essential when using protocols with adaptor signatures.
1194    /// However, it is not essential for regular MuSig's, in the sense that if any
1195    /// partial signatures does not verify, the full signature will also not verify, so the
1196    /// problem will be caught. But this function allows determining the specific party
1197    /// who produced an invalid signature, so that signing can be restarted without them.
1198    ///
1199    /// # Returns:
1200    ///
1201    /// true if the partial signature successfully verifies, otherwise returns false
1202    ///
1203    /// # Arguments:
1204    ///
1205    /// * `secp` : [`Secp256k1`] context object initialized for signing
1206    /// * `key_agg_cache`: [`KeyAggCache`] containing the aggregate pubkey used in
1207    ///   the creation of this session
1208    /// * `partial_sig`: [`PartialSignature`] sent by the signer associated with
1209    ///   the given `pub_nonce` and `pubkey`
1210    /// * `pub_nonce`: The [`PublicNonce`] of the signer associated with the `partial_sig`
1211    ///   and `pub_key`
1212    /// * `pub_key`: The [`XOnlyPublicKey`] of the signer associated with the given
1213    ///   `partial_sig` and `pub_nonce`
1214    ///
1215    /// Example:
1216    ///
1217    /// ```rust
1218    /// # #[cfg(not(secp256k1_fuzz))]
1219    /// # #[cfg(feature = "std")]
1220    /// # #[cfg(feature = "rand")] {
1221    /// # use secp256k1::{SecretKey, Keypair, PublicKey};
1222    /// # use secp256k1::musig::{AggregatedNonce, KeyAggCache, SessionSecretRand, Session};
1223    /// # let sk1 = SecretKey::new(&mut rand::rng());
1224    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
1225    /// # let sk2 = SecretKey::new(&mut rand::rng());
1226    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
1227    ///
1228    /// # let key_agg_cache = KeyAggCache::new(&[&pub_key1, &pub_key2]);
1229    /// // The session id must be sampled at random. Read documentation for more details.
1230    ///
1231    /// let msg = b"Public message we want to sign!!";
1232    ///
1233    /// // Provide the current time for mis-use resistance
1234    /// let session_secrand1 = SessionSecretRand::from_rng(&mut rand::rng());
1235    /// let (mut sec_nonce1, pub_nonce1) = key_agg_cache.nonce_gen(session_secrand1, pub_key1, msg, None);
1236    ///
1237    /// // Signer two does the same. Possibly on a different device
1238    /// let session_secrand2 = SessionSecretRand::from_rng(&mut rand::rng());
1239    /// let (_sec_nonce2, pub_nonce2) = key_agg_cache.nonce_gen(session_secrand2, pub_key2, msg, None);
1240    ///
1241    /// let aggnonce = AggregatedNonce::new(&[&pub_nonce1, &pub_nonce2]);
1242    ///
1243    /// let session = Session::new(
1244    ///     &key_agg_cache,
1245    ///     aggnonce,
1246    ///     msg,
1247    /// );
1248    ///
1249    /// let keypair = Keypair::from_secret_key(&sk1);
1250    /// let partial_sig1 = session.partial_sign(
1251    ///     sec_nonce1,
1252    ///     &keypair,
1253    ///     &key_agg_cache,
1254    /// );
1255    ///
1256    /// assert!(session.partial_verify(
1257    ///     &key_agg_cache,
1258    ///     &partial_sig1,
1259    ///     &pub_nonce1,
1260    ///     pub_key1,
1261    /// ));
1262    /// # }
1263    /// ```
1264    pub fn partial_verify(
1265        &self,
1266        key_agg_cache: &KeyAggCache,
1267        partial_sig: &PartialSignature,
1268        pub_nonce: &PublicNonce,
1269        pub_key: PublicKey,
1270    ) -> bool {
1271        unsafe {
1272            let ret = crate::with_global_context(
1273                |secp: &Secp256k1<crate::AllPreallocated>| {
1274                    ffi::secp256k1_musig_partial_sig_verify(
1275                        secp.ctx.as_ptr(),
1276                        partial_sig.as_ptr(),
1277                        pub_nonce.as_ptr(),
1278                        pub_key.as_c_ptr(),
1279                        key_agg_cache.as_ptr(),
1280                        self.as_ptr(),
1281                    )
1282                },
1283                None,
1284            );
1285            ret == 1
1286        }
1287    }
1288
1289    /// Aggregate partial signatures for this session into a single [`schnorr::Signature`]
1290    ///
1291    /// # Returns:
1292    ///
1293    /// A single [`schnorr::Signature`]. Note that this does *NOT* mean that the signature verifies with respect to the
1294    /// aggregate public key.
1295    ///
1296    /// # Arguments:
1297    ///
1298    /// * `partial_sigs`: Array of [`PartialSignature`] to be aggregated
1299    ///
1300    /// ```rust
1301    /// # #[cfg(feature = "rand-std")] {
1302    /// # use secp256k1::{KeyAggCache, SecretKey, Keypair, PublicKey, SessionSecretRand, AggregatedNonce, Session};
1303    /// # let sk1 = SecretKey::new(&mut rand::rng());
1304    /// # let pub_key1 = PublicKey::from_secret_key(&sk1);
1305    /// # let sk2 = SecretKey::new(&mut rand::rng());
1306    /// # let pub_key2 = PublicKey::from_secret_key(&sk2);
1307    ///
1308    /// let key_agg_cache = KeyAggCache::new(&[pub_key1, pub_key2]);
1309    /// // The session id must be sampled at random. Read documentation for more details.
1310    ///
1311    /// let msg = b"Public message we want to sign!!";
1312    ///
1313    /// // Provide the current time for mis-use resistance
1314    /// let session_secrand1 = SessionSecretRand::from_rng(&mut rand::rng());
1315    /// let (mut sec_nonce1, pub_nonce1) = key_agg_cache.nonce_gen(session_secrand1, pub_key1, msg, None)
1316    ///     .expect("non zero session id");
1317    ///
1318    /// // Signer two does the same. Possibly on a different device
1319    /// let session_secrand2 = SessionSecretRand::from_rng(&mut rand::rng());
1320    /// let (mut sec_nonce2, pub_nonce2) = key_agg_cache.nonce_gen(session_secrand2, pub_key2, msg, None)
1321    ///     .expect("non zero session id");
1322    ///
1323    /// let aggnonce = AggregatedNonce::new(&[pub_nonce1, pub_nonce2]);
1324    ///
1325    /// let session = Session::new(
1326    ///     &key_agg_cache,
1327    ///     aggnonce,
1328    ///     msg,
1329    /// );
1330    ///
1331    /// let partial_sig1 = session.partial_sign(
1332    ///     sec_nonce1,
1333    ///     &Keypair::from_secret_key(&sk1),
1334    ///     &key_agg_cache,
1335    /// ).unwrap();
1336    ///
1337    /// // Other party creates the other partial signature
1338    /// let partial_sig2 = session.partial_sign(
1339    ///     sec_nonce2,
1340    ///     &Keypair::from_secret_key(&sk2),
1341    ///     &key_agg_cache,
1342    /// ).unwrap();
1343    ///
1344    /// let partial_sigs = [partial_sign1, partial_sign2];
1345    /// let partial_sigs_ref: Vec<&PartialSignature> = partial_sigs.iter().collect();
1346    /// let partial_sigs_ref = partial_sigs_ref.as_slice();
1347    ///
1348    /// let aggregated_signature = session.partial_sig_agg(partial_sigs_ref);
1349    ///
1350    /// // Get the final schnorr signature
1351    /// assert!(aggregated_signature.verify(&agg_pk, &msg_bytes).is_ok());
1352    /// # }
1353    /// ```
1354    ///
1355    /// # Panics
1356    ///
1357    /// Panics if an empty slice of partial signatures is provided.
1358    pub fn partial_sig_agg(&self, partial_sigs: &[&PartialSignature]) -> AggregatedSignature {
1359        if partial_sigs.is_empty() {
1360            panic!("Cannot aggregate an empty slice of partial signatures");
1361        }
1362
1363        let mut sig = [0u8; 64];
1364        unsafe {
1365            let partial_sigs_ref = core::slice::from_raw_parts(
1366                partial_sigs.as_ptr() as *const *const ffi::MusigPartialSignature,
1367                partial_sigs.len(),
1368            );
1369
1370            if ffi::secp256k1_musig_partial_sig_agg(
1371                ffi::secp256k1_context_no_precomp,
1372                sig.as_mut_ptr(),
1373                self.as_ptr(),
1374                partial_sigs_ref.as_ptr(),
1375                partial_sigs_ref.len(),
1376            ) == 0
1377            {
1378                // All arguments are well-typed partial signatures
1379                unreachable!("Impossible to construct invalid(not well-typed) partial signatures")
1380            } else {
1381                // Resulting signature must be well-typed. Does not mean that will be succeed verification
1382                AggregatedSignature(sig)
1383            }
1384        }
1385    }
1386
1387    /// Get a const pointer to the inner Session
1388    pub fn as_ptr(&self) -> *const ffi::MusigSession { &self.0 }
1389
1390    /// Get a mut pointer to the inner Session
1391    pub fn as_mut_ptr(&mut self) -> *mut ffi::MusigSession { &mut self.0 }
1392}
1393
1394#[cfg(test)]
1395mod tests {
1396    use super::*;
1397    #[cfg(feature = "std")]
1398    #[cfg(feature = "rand")]
1399    use crate::PublicKey;
1400
1401    #[test]
1402    #[cfg(feature = "std")]
1403    #[cfg(feature = "rand")]
1404    fn session_secret_rand() {
1405        let mut rng = rand::rng();
1406        let session_secrand = SessionSecretRand::from_rng(&mut rng);
1407        let session_secrand1 = SessionSecretRand::from_rng(&mut rng);
1408        assert_ne!(session_secrand.to_byte_array(), [0; 32]); // with overwhelming probability
1409        assert_ne!(session_secrand, session_secrand1); // with overwhelming probability
1410    }
1411
1412    #[test]
1413    fn session_secret_no_rand() {
1414        let custom_bytes = [42u8; 32];
1415        let session_secrand = SessionSecretRand::assume_unique_per_nonce_gen(custom_bytes);
1416        assert_eq!(session_secrand.to_byte_array(), custom_bytes);
1417        assert_eq!(session_secrand.as_byte_array(), &custom_bytes);
1418    }
1419
1420    #[test]
1421    #[should_panic(expected = "session secrets may not be all zero")]
1422    fn session_secret_rand_zero_panic() {
1423        let zero_bytes = [0u8; 32];
1424        let _session_secrand = SessionSecretRand::assume_unique_per_nonce_gen(zero_bytes);
1425    }
1426
1427    #[test]
1428    #[cfg(not(secp256k1_fuzz))]
1429    #[cfg(feature = "std")]
1430    fn key_agg_cache() {
1431        let (_seckey1, pubkey1) = crate::test_random_keypair();
1432        let (_seckey2, pubkey2) = crate::test_random_keypair();
1433
1434        let pubkeys = [&pubkey1, &pubkey2];
1435        let key_agg_cache = KeyAggCache::new(&pubkeys);
1436        let agg_pk = key_agg_cache.agg_pk();
1437
1438        // Test agg_pk_full
1439        let agg_pk_full = key_agg_cache.agg_pk_full();
1440        assert_eq!(agg_pk_full.x_only_public_key().0, agg_pk);
1441    }
1442
1443    #[test]
1444    #[cfg(not(secp256k1_fuzz))]
1445    #[cfg(feature = "std")]
1446    fn key_agg_cache_tweaking() {
1447        let (_seckey1, pubkey1) = crate::test_random_keypair();
1448        let (_seckey2, pubkey2) = crate::test_random_keypair();
1449
1450        let mut key_agg_cache = KeyAggCache::new(&[&pubkey1, &pubkey2]);
1451        let key_agg_cache1 = KeyAggCache::new(&[&pubkey2, &pubkey1]);
1452        let key_agg_cache2 = KeyAggCache::new(&[&pubkey1, &pubkey1]);
1453        let key_agg_cache3 = KeyAggCache::new(&[&pubkey1, &pubkey1, &pubkey2]);
1454        assert_ne!(key_agg_cache, key_agg_cache1); // swapped keys DOES mean not equal
1455        assert_ne!(key_agg_cache, key_agg_cache2); // missing keys
1456        assert_ne!(key_agg_cache, key_agg_cache3); // repeated key
1457        let original_agg_pk = key_agg_cache.agg_pk();
1458        assert_ne!(key_agg_cache.agg_pk(), key_agg_cache1.agg_pk()); // swapped keys DOES mean not equal
1459        assert_ne!(key_agg_cache.agg_pk(), key_agg_cache2.agg_pk()); // missing keys
1460        assert_ne!(key_agg_cache.agg_pk(), key_agg_cache3.agg_pk()); // repeated key
1461
1462        // Test EC tweaking
1463        let plain_tweak: [u8; 32] = *b"this could be a BIP32 tweak....\0";
1464        let plain_tweak = Scalar::from_be_bytes(plain_tweak).unwrap();
1465        let tweaked_key = key_agg_cache.pubkey_ec_tweak_add(&plain_tweak).unwrap();
1466        assert_ne!(key_agg_cache.agg_pk(), original_agg_pk);
1467        assert_eq!(key_agg_cache.agg_pk(), tweaked_key.x_only_public_key().0);
1468
1469        // Test xonly tweaking
1470        let xonly_tweak: [u8; 32] = *b"this could be a Taproot tweak..\0";
1471        let xonly_tweak = Scalar::from_be_bytes(xonly_tweak).unwrap();
1472        let tweaked_agg_pk = key_agg_cache.pubkey_xonly_tweak_add(&xonly_tweak).unwrap();
1473        assert_eq!(key_agg_cache.agg_pk(), tweaked_agg_pk.x_only_public_key().0);
1474    }
1475
1476    #[test]
1477    #[cfg(feature = "std")]
1478    #[should_panic(expected = "Cannot aggregate an empty slice of pubkeys")]
1479    fn key_agg_cache_empty_panic() { let _ = KeyAggCache::new(&[]); }
1480
1481    #[test]
1482    #[cfg(feature = "std")]
1483    #[cfg(feature = "rand")]
1484    fn nonce_generation() {
1485        let mut rng = rand::rng();
1486
1487        let (_seckey1, pubkey1) = crate::test_random_keypair();
1488        let (seckey2, pubkey2) = crate::test_random_keypair();
1489
1490        let key_agg_cache = KeyAggCache::new(&[&pubkey1, &pubkey2]);
1491
1492        let msg: &[u8; 32] = b"This message is exactly 32 bytes";
1493
1494        // Test nonce generation with KeyAggCache
1495        let session_secrand1 = SessionSecretRand::from_rng(&mut rng);
1496        let (_sec_nonce1, pub_nonce1) =
1497            key_agg_cache.nonce_gen(session_secrand1, pubkey1, msg, None);
1498
1499        // Test direct nonce generation
1500        let session_secrand2 = SessionSecretRand::from_rng(&mut rng);
1501        let extra_rand = Some([42u8; 32]);
1502        let (_sec_nonce2, _pub_nonce2) = new_nonce_pair(
1503            session_secrand2,
1504            Some(&key_agg_cache),
1505            Some(seckey2),
1506            pubkey2,
1507            Some(msg),
1508            extra_rand,
1509        );
1510
1511        // Test PublicNonce serialization/deserialization
1512        let serialized_nonce = pub_nonce1.serialize();
1513        let deserialized_nonce = PublicNonce::from_byte_array(&serialized_nonce).unwrap();
1514        assert_eq!(pub_nonce1.serialize(), deserialized_nonce.serialize());
1515    }
1516
1517    #[test]
1518    #[cfg(feature = "std")]
1519    #[cfg(feature = "rand")]
1520    fn aggregated_nonce() {
1521        let mut rng = rand::rng();
1522
1523        let (_seckey1, pubkey1) = crate::test_random_keypair();
1524        let (_seckey2, pubkey2) = crate::test_random_keypair();
1525
1526        let key_agg_cache = KeyAggCache::new(&[&pubkey1, &pubkey2]);
1527
1528        let msg: &[u8; 32] = b"This message is exactly 32 bytes";
1529
1530        let session_secrand1 = SessionSecretRand::from_rng(&mut rng);
1531        let (_, pub_nonce1) = key_agg_cache.nonce_gen(session_secrand1, pubkey1, msg, None);
1532
1533        let session_secrand2 = SessionSecretRand::from_rng(&mut rng);
1534        let (_, pub_nonce2) = key_agg_cache.nonce_gen(session_secrand2, pubkey2, msg, None);
1535
1536        // Test AggregatedNonce creation
1537        let agg_nonce = AggregatedNonce::new(&[&pub_nonce1, &pub_nonce2]);
1538        let agg_nonce1 = AggregatedNonce::new(&[&pub_nonce2, &pub_nonce1]);
1539        let agg_nonce2 = AggregatedNonce::new(&[&pub_nonce2, &pub_nonce2]);
1540        let agg_nonce3 = AggregatedNonce::new(&[&pub_nonce2, &pub_nonce2]);
1541        assert_eq!(agg_nonce, agg_nonce1); // swapped nonces
1542        assert_ne!(agg_nonce, agg_nonce2); // repeated/different nonces
1543        assert_ne!(agg_nonce, agg_nonce3); // repeated nonce but still both nonces present
1544
1545        // Test AggregatedNonce serialization/deserialization
1546        let serialized_agg_nonce = agg_nonce.serialize();
1547        let deserialized_agg_nonce =
1548            AggregatedNonce::from_byte_array(&serialized_agg_nonce).unwrap();
1549        assert_eq!(agg_nonce.serialize(), deserialized_agg_nonce.serialize());
1550    }
1551
1552    #[test]
1553    #[cfg(feature = "std")]
1554    #[should_panic(expected = "Cannot aggregate an empty slice of nonces")]
1555    fn aggregated_nonce_empty_panic() {
1556        let empty_nonces: Vec<&PublicNonce> = vec![];
1557        let _agg_nonce = AggregatedNonce::new(&empty_nonces);
1558    }
1559
1560    #[test]
1561    #[cfg(not(secp256k1_fuzz))]
1562    #[cfg(feature = "std")]
1563    #[cfg(feature = "rand")]
1564    fn session_and_partial_signing() {
1565        let mut rng = rand::rng();
1566
1567        let (seckey1, pubkey1) = crate::test_random_keypair();
1568        let (seckey2, pubkey2) = crate::test_random_keypair();
1569
1570        let pubkeys = [&pubkey1, &pubkey2];
1571        let key_agg_cache = KeyAggCache::new(&pubkeys);
1572
1573        let msg: &[u8; 32] = b"This message is exactly 32 bytes";
1574
1575        let session_secrand1 = SessionSecretRand::from_rng(&mut rng);
1576        let (sec_nonce1, pub_nonce1) =
1577            key_agg_cache.nonce_gen(session_secrand1, pubkey1, msg, None);
1578
1579        let session_secrand2 = SessionSecretRand::from_rng(&mut rng);
1580        let (sec_nonce2, pub_nonce2) =
1581            key_agg_cache.nonce_gen(session_secrand2, pubkey2, msg, None);
1582
1583        let nonces = [&pub_nonce1, &pub_nonce2];
1584        let agg_nonce = AggregatedNonce::new(&nonces);
1585
1586        // Test Session creation
1587        let session = Session::new(&key_agg_cache, agg_nonce, msg);
1588
1589        // Test partial signing
1590        let keypair1 = Keypair::from_secret_key(&seckey1);
1591        let partial_sign1 = session.partial_sign(sec_nonce1, &keypair1, &key_agg_cache);
1592
1593        let keypair2 = Keypair::from_secret_key(&seckey2);
1594        let partial_sign2 = session.partial_sign(sec_nonce2, &keypair2, &key_agg_cache);
1595
1596        // Test partial signature verification
1597        assert!(session.partial_verify(&key_agg_cache, &partial_sign1, &pub_nonce1, pubkey1));
1598        assert!(session.partial_verify(&key_agg_cache, &partial_sign2, &pub_nonce2, pubkey2));
1599        // Test that they are invalid if you switch keys
1600        assert!(!session.partial_verify(&key_agg_cache, &partial_sign2, &pub_nonce2, pubkey1));
1601        assert!(!session.partial_verify(&key_agg_cache, &partial_sign2, &pub_nonce1, pubkey2));
1602        assert!(!session.partial_verify(&key_agg_cache, &partial_sign2, &pub_nonce1, pubkey1));
1603
1604        // Test PartialSignature serialization/deserialization
1605        let serialized_partial_sig = partial_sign1.serialize();
1606        let deserialized_partial_sig =
1607            PartialSignature::from_byte_array(&serialized_partial_sig).unwrap();
1608        assert_eq!(partial_sign1.serialize(), deserialized_partial_sig.serialize());
1609    }
1610
1611    #[test]
1612    #[cfg(not(secp256k1_fuzz))]
1613    #[cfg(feature = "std")]
1614    #[cfg(feature = "rand")]
1615    fn signature_aggregation_and_verification() {
1616        let mut rng = rand::rng();
1617
1618        let (seckey1, pubkey1) = crate::test_random_keypair();
1619        let (seckey2, pubkey2) = crate::test_random_keypair();
1620
1621        let pubkeys = [&pubkey1, &pubkey2];
1622        let key_agg_cache = KeyAggCache::new(&pubkeys);
1623
1624        let msg: &[u8; 32] = b"This message is exactly 32 bytes";
1625
1626        let session_secrand1 = SessionSecretRand::from_rng(&mut rng);
1627        let (sec_nonce1, pub_nonce1) =
1628            key_agg_cache.nonce_gen(session_secrand1, pubkey1, msg, None);
1629
1630        let session_secrand2 = SessionSecretRand::from_rng(&mut rng);
1631        let (sec_nonce2, pub_nonce2) =
1632            key_agg_cache.nonce_gen(session_secrand2, pubkey2, msg, None);
1633
1634        let nonces = [&pub_nonce1, &pub_nonce2];
1635        let agg_nonce = AggregatedNonce::new(&nonces);
1636        let session = Session::new(&key_agg_cache, agg_nonce, msg);
1637
1638        let keypair1 = Keypair::from_secret_key(&seckey1);
1639        let partial_sign1 = session.partial_sign(sec_nonce1, &keypair1, &key_agg_cache);
1640
1641        let keypair2 = Keypair::from_secret_key(&seckey2);
1642        let partial_sign2 = session.partial_sign(sec_nonce2, &keypair2, &key_agg_cache);
1643
1644        // Test signature verification
1645        let aggregated_signature = session.partial_sig_agg(&[&partial_sign1, &partial_sign2]);
1646        let agg_pk = key_agg_cache.agg_pk();
1647        aggregated_signature.verify(&agg_pk, msg).unwrap();
1648
1649        // Test assume_valid
1650        let schnorr_sig = aggregated_signature.assume_valid();
1651        schnorr::verify(&schnorr_sig, msg, &agg_pk).unwrap();
1652
1653        // Test with wrong aggregate (repeated sigs)
1654        let aggregated_signature = session.partial_sig_agg(&[&partial_sign1, &partial_sign1]);
1655        aggregated_signature.verify(&agg_pk, msg).unwrap_err();
1656        let schnorr_sig = aggregated_signature.assume_valid();
1657        schnorr::verify(&schnorr_sig, msg, &agg_pk).unwrap_err();
1658
1659        // Test with swapped sigs -- this will work. Unlike keys, sigs are not ordered.
1660        let aggregated_signature = session.partial_sig_agg(&[&partial_sign2, &partial_sign1]);
1661        aggregated_signature.verify(&agg_pk, msg).unwrap();
1662        let schnorr_sig = aggregated_signature.assume_valid();
1663        schnorr::verify(&schnorr_sig, msg, &agg_pk).unwrap();
1664    }
1665
1666    #[test]
1667    #[cfg(feature = "std")]
1668    #[cfg(feature = "rand")]
1669    #[should_panic(expected = "Cannot aggregate an empty slice of partial signatures")]
1670    fn partial_sig_agg_empty_panic() {
1671        let mut rng = rand::rng();
1672
1673        let (_seckey1, pubkey1) = crate::test_random_keypair();
1674        let (_seckey2, pubkey2) = crate::test_random_keypair();
1675
1676        let pubkeys = [pubkey1, pubkey2];
1677        let mut pubkeys_ref: Vec<&PublicKey> = pubkeys.iter().collect();
1678        let pubkeys_ref = pubkeys_ref.as_mut_slice();
1679
1680        let key_agg_cache = KeyAggCache::new(pubkeys_ref);
1681        let msg: &[u8; 32] = b"This message is exactly 32 bytes";
1682
1683        let session_secrand1 = SessionSecretRand::from_rng(&mut rng);
1684        let (_, pub_nonce1) = key_agg_cache.nonce_gen(session_secrand1, pubkey1, msg, None);
1685        let session_secrand2 = SessionSecretRand::from_rng(&mut rng);
1686        let (_, pub_nonce2) = key_agg_cache.nonce_gen(session_secrand2, pubkey2, msg, None);
1687
1688        let nonces = [pub_nonce1, pub_nonce2];
1689        let nonces_ref: Vec<&PublicNonce> = nonces.iter().collect();
1690        let agg_nonce = AggregatedNonce::new(&nonces_ref);
1691        let session = Session::new(&key_agg_cache, agg_nonce, msg);
1692
1693        let _agg_sig = session.partial_sig_agg(&[]);
1694    }
1695
1696    #[test]
1697    fn de_serialization() {
1698        const MUSIG_PUBLIC_NONCE_HEX: &str = "03f4a361abd3d50535be08421dbc73b0a8f595654ae3238afcaf2599f94e25204c036ba174214433e21f5cd0fcb14b038eb40b05b7e7c820dd21aa568fdb0a9de4d7";
1699        let pubnonce: PublicNonce = MUSIG_PUBLIC_NONCE_HEX.parse().unwrap();
1700
1701        assert_eq!(pubnonce.to_string(), MUSIG_PUBLIC_NONCE_HEX);
1702
1703        const MUSIG_AGGREGATED_NONCE_HEX: &str = "0218c30fe0f567a4a9c05eb4835e2735419cf30f834c9ce2fe3430f021ba4eacd503112e97bcf6a022d236d71a9357824a2b19515f980131b3970b087cadf94cc4a7";
1704        let aggregated_nonce: AggregatedNonce = MUSIG_AGGREGATED_NONCE_HEX.parse().unwrap();
1705        assert_eq!(aggregated_nonce.to_string(), MUSIG_AGGREGATED_NONCE_HEX);
1706
1707        const MUSIG_PARTIAL_SIGNATURE_HEX: &str =
1708            "289eeb2f5efc314aa6d87bf58125043c96d15a007db4b6aaaac7d18086f49a99";
1709        let partial_signature: PartialSignature = MUSIG_PARTIAL_SIGNATURE_HEX.parse().unwrap();
1710        assert_eq!(partial_signature.to_string(), MUSIG_PARTIAL_SIGNATURE_HEX);
1711    }
1712}