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