ark/
musig.rs

1
2use std::fmt;
3
4pub use secp256k1_musig as secpm;
5pub use secp256k1_musig::musig::{
6	AggregatedNonce, PublicNonce, PartialSignature, SecretNonce, Session, SessionSecretRand,
7};
8
9
10use bitcoin::secp256k1::{schnorr, Keypair, PublicKey, SecretKey, XOnlyPublicKey};
11use secpm::ffi::MUSIG_SECNONCE_SIZE;
12use secpm::musig::KeyAggCache;
13
14lazy_static! {
15	/// Global secp context.
16	pub static ref SECP: secpm::Secp256k1<secpm::All> = secpm::Secp256k1::new();
17}
18
19pub fn xonly_from(pk: secpm::XOnlyPublicKey) -> XOnlyPublicKey {
20	XOnlyPublicKey::from_slice(&pk.serialize()).unwrap()
21}
22
23pub fn pubkey_to(pk: PublicKey) -> secpm::PublicKey {
24	secpm::PublicKey::from_slice(&pk.serialize_uncompressed()).unwrap()
25}
26
27pub fn pubkey_from(pk: secpm::PublicKey) -> PublicKey {
28	PublicKey::from_slice(&pk.serialize_uncompressed()).unwrap()
29}
30
31pub fn seckey_to(sk: SecretKey) -> secpm::SecretKey {
32	secpm::SecretKey::from_secret_bytes(sk.secret_bytes()).unwrap()
33}
34
35pub fn keypair_to(kp: &Keypair) -> secpm::Keypair {
36	secpm::Keypair::from_seckey_byte_array(kp.secret_bytes()).unwrap()
37}
38
39pub fn keypair_from(kp: &secpm::Keypair) -> Keypair {
40	Keypair::from_seckey_slice(&crate::SECP, &kp.secret_bytes()).unwrap()
41}
42
43pub fn sig_from(s: secpm::schnorr::Signature) -> schnorr::Signature {
44	schnorr::Signature::from_slice(&s.to_byte_array()).unwrap()
45}
46
47/// Returns the key agg cache and the resulting pubkey.
48///
49/// Key order is not important as keys are sorted before aggregation.
50pub fn key_agg<'a>(keys: impl IntoIterator<Item = PublicKey>) -> KeyAggCache {
51	let mut keys = keys.into_iter().map(|k| pubkey_to(k)).collect::<Vec<_>>();
52	keys.sort_by_key(|k| k.serialize());
53	let keys = keys.iter().collect::<Vec<_>>(); //TODO(stevenroose) remove when musig pr merged
54	KeyAggCache::new(&keys)
55}
56
57/// Returns the key agg cache with the tweak applied and the resulting pubkey
58/// with the tweak applied.
59///
60/// Key order is not important as keys are sorted before aggregation.
61pub fn tweaked_key_agg<'a>(
62	keys: impl IntoIterator<Item = PublicKey>,
63	tweak: [u8; 32],
64) -> (KeyAggCache, PublicKey) {
65	let mut keys = keys.into_iter().map(|k| pubkey_to(k)).collect::<Vec<_>>();
66	keys.sort_by_key(|k| k.serialize());
67	let keys = keys.iter().collect::<Vec<_>>(); //TODO(stevenroose) remove when musig pr merged
68	let mut ret = KeyAggCache::new(&keys);
69	let tweak_scalar = secpm::Scalar::from_be_bytes(tweak).unwrap();
70	let pk = ret.pubkey_xonly_tweak_add(&tweak_scalar).unwrap();
71	(ret, pubkey_from(pk))
72}
73
74/// Aggregates the public keys into their aggregate public key.
75///
76/// Key order is not important as keys are sorted before aggregation.
77pub fn combine_keys(keys: impl IntoIterator<Item = PublicKey>) -> XOnlyPublicKey {
78	xonly_from(key_agg(keys).agg_pk())
79}
80
81pub fn nonce_pair(key: &Keypair) -> (SecretNonce, PublicNonce) {
82	let kp = keypair_to(key);
83	secpm::musig::new_nonce_pair(
84		SessionSecretRand::assume_unique_per_nonce_gen(rand::random()),
85		None,
86		Some(kp.secret_key()),
87		kp.public_key(),
88		None,
89		Some(rand::random()),
90	)
91}
92
93pub fn nonce_pair_with_msg(key: &Keypair, msg: &[u8; 32]) -> (SecretNonce, PublicNonce) {
94	let kp = keypair_to(key);
95	secpm::musig::new_nonce_pair(
96		SessionSecretRand::assume_unique_per_nonce_gen(rand::random()),
97		None,
98		Some(kp.secret_key()),
99		kp.public_key(),
100		Some(msg),
101		Some(rand::random()),
102	)
103}
104
105pub fn nonce_agg(pub_nonces: &[&PublicNonce]) -> AggregatedNonce {
106	AggregatedNonce::new(pub_nonces)
107}
108
109pub fn combine_partial_signatures(
110	pubkeys: impl IntoIterator<Item = PublicKey>,
111	agg_nonce: AggregatedNonce,
112	sighash: [u8; 32],
113	tweak: Option<[u8; 32]>,
114	sigs: &[&PartialSignature],
115) -> schnorr::Signature {
116	let agg = if let Some(tweak) = tweak {
117		tweaked_key_agg(pubkeys, tweak).0
118	} else {
119		key_agg(pubkeys)
120	};
121
122	let session = Session::new(&agg, agg_nonce, &sighash);
123	sig_from(session.partial_sig_agg(&sigs).assume_valid())
124}
125
126pub fn partial_sign(
127	pubkeys: impl IntoIterator<Item = PublicKey>,
128	agg_nonce: AggregatedNonce,
129	key: &Keypair,
130	sec_nonce: SecretNonce,
131	sighash: [u8; 32],
132	tweak: Option<[u8; 32]>,
133	other_sigs: Option<&[&PartialSignature]>,
134) -> (PartialSignature, Option<schnorr::Signature>) {
135	let agg = if let Some(tweak) = tweak {
136		tweaked_key_agg(pubkeys, tweak).0
137	} else {
138		key_agg(pubkeys)
139	};
140
141	let session = Session::new(&agg, agg_nonce, &sighash);
142	let my_sig = session.partial_sign(sec_nonce, &keypair_to(&key), &agg);
143	let final_sig = if let Some(others) = other_sigs {
144		let mut sigs = Vec::with_capacity(others.len() + 1);
145		sigs.extend_from_slice(others);
146		sigs.push(&my_sig);
147		Some(session.partial_sig_agg(&sigs))
148	} else {
149		None
150	};
151	(my_sig, final_sig.map(|s| sig_from(s.assume_valid())))
152}
153
154/// Perform a deterministic partial sign for the given message and the
155/// given counterparty key and nonce.
156///
157/// This is only possible for the first party to sign if it has all the
158/// counterparty nonces.
159pub fn deterministic_partial_sign(
160	my_key: &Keypair,
161	their_pubkeys: impl IntoIterator<Item = PublicKey>,
162	their_nonces: &[&PublicNonce],
163	msg: [u8; 32],
164	tweak: Option<[u8; 32]>,
165) -> (PublicNonce, PartialSignature) {
166	let agg = if let Some(tweak) = tweak {
167		tweaked_key_agg(their_pubkeys.into_iter().chain(Some(my_key.public_key())), tweak).0
168	} else {
169		key_agg(their_pubkeys.into_iter().chain(Some(my_key.public_key())))
170	};
171
172	let (sec_nonce, pub_nonce) = secpm::musig::new_nonce_pair(
173		SessionSecretRand::assume_unique_per_nonce_gen(rand::random()),
174		Some(&agg),
175		Some(seckey_to(my_key.secret_key())),
176		pubkey_to(my_key.public_key()),
177		Some(&msg),
178		Some(rand::random()),
179	);
180
181	let nonces = their_nonces.into_iter().map(|n| *n).chain(Some(&pub_nonce)).collect::<Vec<_>>();
182	let agg_nonce = AggregatedNonce::new(&nonces);
183	let session = Session::new(&agg, agg_nonce, &msg);
184	let sig = session.partial_sign(sec_nonce, &keypair_to(my_key), &agg);
185	(pub_nonce, sig)
186}
187
188//TODO(stevenroose) probably get rid of all this by having native byte serializers in secp
189pub mod serde {
190	use super::*;
191	use ::serde::{Deserializer, Serializer};
192	use ::serde::de::{self, Error};
193
194	pub(super) struct BytesVisitor;
195	impl<'de> de::Visitor<'de> for BytesVisitor {
196		type Value = Vec<u8>;
197		fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198			write!(f, "a byte object")
199		}
200		fn visit_bytes<E: de::Error>(self, v: &[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/// A type that actually represents a [SecretNonce] but without the
232/// typesystem defenses for dangerous usage.
233#[derive(Clone, PartialEq, Eq)]
234pub struct DangerousSecretNonce([u8; MUSIG_SECNONCE_SIZE]);
235
236impl DangerousSecretNonce {
237	pub fn dangerous_from_secret_nonce(n: SecretNonce) -> Self {
238		DangerousSecretNonce(n.dangerous_into_bytes())
239	}
240
241	pub fn to_sec_nonce(&self) -> SecretNonce {
242		SecretNonce::dangerous_from_bytes(self.0.clone())
243	}
244
245	pub fn serialize(&self) -> [u8; MUSIG_SECNONCE_SIZE] {
246		self.0.clone()
247	}
248
249	pub fn from_byte_array(bytes: [u8; MUSIG_SECNONCE_SIZE]) -> Self {
250		Self(bytes)
251	}
252}
253
254impl fmt::Debug for DangerousSecretNonce {
255	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256	    f.write_str("[secret nonces redacted]")
257	}
258}
259
260impl ::serde::Serialize for DangerousSecretNonce {
261	fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
262		s.serialize_bytes(&self.0[..])
263	}
264}
265
266impl<'de> ::serde::Deserialize<'de> for DangerousSecretNonce {
267	fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
268
269		// can eventually use self::serde::BytesVisitor,
270		// but we now also accept lists to be backwards compatible with Vec<u8>
271		struct Visitor;
272		impl<'de> ::serde::de::Visitor<'de> for Visitor {
273			type Value = DangerousSecretNonce;
274			fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275				write!(f, "a sercret musig nonce")
276			}
277			fn visit_bytes<E: ::serde::de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
278				TryFrom::try_from(v)
279					.map(DangerousSecretNonce::from_byte_array)
280					.map_err(|_| ::serde::de::Error::custom("invalid nonce"))
281			}
282			// be compatible with previous serialization
283			fn visit_seq<A: ::serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
284			    let mut buf = Vec::with_capacity(MUSIG_SECNONCE_SIZE);
285				while let Some(e) = seq.next_element::<u8>()? {
286					buf.push(e);
287				}
288
289				TryFrom::try_from(&buf[..])
290					.map(DangerousSecretNonce::from_byte_array)
291					.map_err(|_| ::serde::de::Error::custom("invalid nonce"))
292			}
293		}
294
295		d.deserialize_any(Visitor)
296	}
297}
298
299#[cfg(test)]
300mod test {
301	use super::*;
302
303	#[test]
304	fn check_secnonce_serde_backwards_compat() {
305		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]";
306		let _ = serde_json::from_str::<DangerousSecretNonce>(old_example).unwrap();
307	}
308}