1
2pub use secp256k1_musig as secpm;
3pub use secp256k1_musig::musig::{
4 AggregatedNonce, PublicNonce, PartialSignature, SecretNonce, Session, SessionSecretRand,
5};
6
7
8use bitcoin::secp256k1::{schnorr, Keypair, PublicKey, SecretKey, XOnlyPublicKey};
9use secpm::ffi::MUSIG_SECNONCE_SIZE;
10use secpm::musig::KeyAggCache;
11
12lazy_static! {
13 pub static ref SECP: secpm::Secp256k1<secpm::All> = secpm::Secp256k1::new();
15}
16
17pub fn xonly_from(pk: secpm::XOnlyPublicKey) -> XOnlyPublicKey {
18 XOnlyPublicKey::from_slice(&pk.serialize()).unwrap()
19}
20
21pub fn pubkey_to(pk: PublicKey) -> secpm::PublicKey {
22 secpm::PublicKey::from_slice(&pk.serialize_uncompressed()).unwrap()
23}
24
25pub fn pubkey_from(pk: secpm::PublicKey) -> PublicKey {
26 PublicKey::from_slice(&pk.serialize_uncompressed()).unwrap()
27}
28
29pub fn seckey_to(sk: SecretKey) -> secpm::SecretKey {
30 secpm::SecretKey::from_secret_bytes(sk.secret_bytes()).unwrap()
31}
32
33pub fn keypair_to(kp: &Keypair) -> secpm::Keypair {
34 secpm::Keypair::from_seckey_byte_array(kp.secret_bytes()).unwrap()
35}
36
37pub fn keypair_from(kp: &secpm::Keypair) -> Keypair {
38 Keypair::from_seckey_slice(&crate::SECP, &kp.secret_bytes()).unwrap()
39}
40
41pub fn sig_from(s: secpm::schnorr::Signature) -> schnorr::Signature {
42 schnorr::Signature::from_slice(&s.to_byte_array()).unwrap()
43}
44
45pub fn key_agg<'a>(keys: impl IntoIterator<Item = PublicKey>) -> KeyAggCache {
49 let mut keys = keys.into_iter().map(|k| pubkey_to(k)).collect::<Vec<_>>();
50 keys.sort_by_key(|k| k.serialize());
51 let keys = keys.iter().collect::<Vec<_>>(); KeyAggCache::new(&keys)
53}
54
55pub fn tweaked_key_agg<'a>(
60 keys: impl IntoIterator<Item = PublicKey>,
61 tweak: [u8; 32],
62) -> (KeyAggCache, PublicKey) {
63 let mut keys = keys.into_iter().map(|k| pubkey_to(k)).collect::<Vec<_>>();
64 keys.sort_by_key(|k| k.serialize());
65 let keys = keys.iter().collect::<Vec<_>>(); let mut ret = KeyAggCache::new(&keys);
67 let tweak_scalar = secpm::Scalar::from_be_bytes(tweak).unwrap();
68 let pk = ret.pubkey_xonly_tweak_add(&tweak_scalar).unwrap();
69 (ret, pubkey_from(pk))
70}
71
72pub fn combine_keys(keys: impl IntoIterator<Item = PublicKey>) -> XOnlyPublicKey {
76 xonly_from(key_agg(keys).agg_pk())
77}
78
79pub fn nonce_pair(key: &Keypair) -> (SecretNonce, PublicNonce) {
80 let kp = keypair_to(key);
81 secpm::musig::new_nonce_pair(
82 SessionSecretRand::assume_unique_per_nonce_gen(rand::random()),
83 None,
84 Some(kp.secret_key()),
85 kp.public_key(),
86 None,
87 Some(rand::random()),
88 )
89}
90
91pub fn nonce_pair_with_msg(key: &Keypair, msg: &[u8; 32]) -> (SecretNonce, PublicNonce) {
92 let kp = keypair_to(key);
93 secpm::musig::new_nonce_pair(
94 SessionSecretRand::assume_unique_per_nonce_gen(rand::random()),
95 None,
96 Some(kp.secret_key()),
97 kp.public_key(),
98 Some(msg),
99 Some(rand::random()),
100 )
101}
102
103pub fn nonce_agg(pub_nonces: &[&PublicNonce]) -> AggregatedNonce {
104 AggregatedNonce::new(pub_nonces)
105}
106
107pub fn combine_partial_signatures(
108 pubkeys: impl IntoIterator<Item = PublicKey>,
109 agg_nonce: AggregatedNonce,
110 sighash: [u8; 32],
111 tweak: Option<[u8; 32]>,
112 sigs: &[&PartialSignature],
113) -> schnorr::Signature {
114 let agg = if let Some(tweak) = tweak {
115 tweaked_key_agg(pubkeys, tweak).0
116 } else {
117 key_agg(pubkeys)
118 };
119
120 let session = Session::new(&agg, agg_nonce, &sighash);
121 sig_from(session.partial_sig_agg(&sigs).assume_valid())
122}
123
124pub fn partial_sign(
125 pubkeys: impl IntoIterator<Item = PublicKey>,
126 agg_nonce: AggregatedNonce,
127 key: &Keypair,
128 sec_nonce: SecretNonce,
129 sighash: [u8; 32],
130 tweak: Option<[u8; 32]>,
131 other_sigs: Option<&[&PartialSignature]>,
132) -> (PartialSignature, Option<schnorr::Signature>) {
133 let agg = if let Some(tweak) = tweak {
134 tweaked_key_agg(pubkeys, tweak).0
135 } else {
136 key_agg(pubkeys)
137 };
138
139 let session = Session::new(&agg, agg_nonce, &sighash);
140 let my_sig = session.partial_sign(sec_nonce, &keypair_to(&key), &agg);
141 let final_sig = if let Some(others) = other_sigs {
142 let mut sigs = Vec::with_capacity(others.len() + 1);
143 sigs.extend_from_slice(others);
144 sigs.push(&my_sig);
145 Some(session.partial_sig_agg(&sigs))
146 } else {
147 None
148 };
149 (my_sig, final_sig.map(|s| sig_from(s.assume_valid())))
150}
151
152pub fn deterministic_partial_sign(
158 my_key: &Keypair,
159 their_pubkeys: impl IntoIterator<Item = PublicKey>,
160 their_nonces: &[&PublicNonce],
161 msg: [u8; 32],
162 tweak: Option<[u8; 32]>,
163) -> (PublicNonce, PartialSignature) {
164 let agg = if let Some(tweak) = tweak {
165 tweaked_key_agg(their_pubkeys.into_iter().chain(Some(my_key.public_key())), tweak).0
166 } else {
167 key_agg(their_pubkeys.into_iter().chain(Some(my_key.public_key())))
168 };
169
170 let (sec_nonce, pub_nonce) = secpm::musig::new_nonce_pair(
171 SessionSecretRand::assume_unique_per_nonce_gen(rand::random()),
172 Some(&agg),
173 Some(seckey_to(my_key.secret_key())),
174 pubkey_to(my_key.public_key()),
175 Some(&msg),
176 Some(rand::random()),
177 );
178
179 let nonces = their_nonces.into_iter().map(|n| *n).chain(Some(&pub_nonce)).collect::<Vec<_>>();
180 let agg_nonce = AggregatedNonce::new(&nonces);
181 let session = Session::new(&agg, agg_nonce, &msg);
182 let sig = session.partial_sign(sec_nonce, &keypair_to(my_key), &agg);
183 (pub_nonce, sig)
184}
185
186pub mod serde {
188 use super::*;
189 use ::serde::{Deserializer, Serializer};
190 use ::serde::de::{self, Error};
191
192 pub(super) struct BytesVisitor;
193 impl<'de> de::Visitor<'de> for BytesVisitor {
194 type Value = Vec<u8>;
195 fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196 write!(f, "a byte object")
197 }
198 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
199 Ok(v.to_vec())
200 }
201 fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
202 Ok(v)
203 }
204 }
205
206 pub mod pubnonce {
207 use super::*;
208 pub fn serialize<S: Serializer>(pub_nonce: &PublicNonce, s: S) -> Result<S::Ok, S::Error> {
209 s.serialize_bytes(&pub_nonce.serialize())
210 }
211 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<PublicNonce, D::Error> {
212 let v = d.deserialize_byte_buf(BytesVisitor)?;
213 let b = TryFrom::try_from(&v[..]).map_err(D::Error::custom)?;
214 PublicNonce::from_byte_array(b).map_err(D::Error::custom)
215 }
216 }
217 pub mod partialsig {
218 use super::*;
219 pub fn serialize<S: Serializer>(sig: &PartialSignature, s: S) -> Result<S::Ok, S::Error> {
220 s.serialize_bytes(&sig.serialize())
221 }
222 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<PartialSignature, D::Error> {
223 let v = d.deserialize_byte_buf(BytesVisitor)?;
224 let b = TryFrom::try_from(&v[..]).map_err(D::Error::custom)?;
225 PartialSignature::from_byte_array(b).map_err(D::Error::custom)
226 }
227 }
228}
229#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct DangerousSecretNonce([u8; MUSIG_SECNONCE_SIZE]);
233
234impl DangerousSecretNonce {
235 pub fn dangerous_from_secret_nonce(n: SecretNonce) -> Self {
236 DangerousSecretNonce(n.dangerous_into_bytes())
237 }
238
239 pub fn to_sec_nonce(&self) -> SecretNonce {
240 SecretNonce::dangerous_from_bytes(self.0.clone())
241 }
242
243 pub fn serialize(&self) -> [u8; MUSIG_SECNONCE_SIZE] {
244 self.0.clone()
245 }
246
247 pub fn from_byte_array(bytes: [u8; MUSIG_SECNONCE_SIZE]) -> Self {
248 Self(bytes)
249 }
250}
251
252impl ::serde::Serialize for DangerousSecretNonce {
253 fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
254 s.serialize_bytes(&self.0[..])
255 }
256}
257
258impl<'de> ::serde::Deserialize<'de> for DangerousSecretNonce {
259 fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
260
261 struct Visitor;
264 impl<'de> ::serde::de::Visitor<'de> for Visitor {
265 type Value = DangerousSecretNonce;
266 fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267 write!(f, "a sercret musig nonce")
268 }
269 fn visit_bytes<E: ::serde::de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
270 TryFrom::try_from(v)
271 .map(DangerousSecretNonce::from_byte_array)
272 .map_err(|_| ::serde::de::Error::custom("invalid nonce"))
273 }
274 fn visit_seq<A: ::serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
276 let mut buf = Vec::with_capacity(MUSIG_SECNONCE_SIZE);
277 while let Some(e) = seq.next_element::<u8>()? {
278 buf.push(e);
279 }
280
281 TryFrom::try_from(&buf[..])
282 .map(DangerousSecretNonce::from_byte_array)
283 .map_err(|_| ::serde::de::Error::custom("invalid nonce"))
284 }
285 }
286
287 d.deserialize_any(Visitor)
288 }
289}
290
291#[cfg(test)]
292mod test {
293 use super::*;
294
295 #[test]
296 fn check_secnonce_serde_backwards_compat() {
297 let old_example = "[34,14,220,241,180,58,27,107,242,94,46,188,49,93,184,43,106,56,122,169,152,94,66,191,174,151,204,92,46,98,136,90,36,157,87,31,121,220,132,111,215,45,84,171,202,93,147,0,95,177,81,31,9,178,49,66,6,46,48,146,122,120,169,193,196,26,248,12,254,130,145,44,72,98,212,216,130,188,160,32,233,255,151,175,212,179,236,166,29,124,170,6,105,95,89,39,57,90,229,234,160,79,115,5,71,11,180,46,211,198,109,140,248,12,53,4,246,201,129,87,194,97,237,214,255,196,105,121,180,98,60,132]";
298 let _ = serde_json::from_str::<DangerousSecretNonce>(old_example).unwrap();
299 }
300}