Skip to content

Commit 345bdde

Browse files
committed
update most of docs
Signed-off-by: nickfarrow <[email protected]>
1 parent 58afcd3 commit 345bdde

File tree

1 file changed

+58
-87
lines changed

1 file changed

+58
-87
lines changed

schnorr_fun/src/musig.rs

Lines changed: 58 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,41 @@
88
//! // use sha256 with deterministic nonce generation
99
//! let musig = MuSig::<Sha256, Schnorr<Sha256, Deterministic<Sha256>>>::default();
1010
//! // create a keylist
11-
//! # use schnorr_fun::fun::Scalar;
12-
//! # let kp1 = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng()));
11+
//! use schnorr_fun::fun::Scalar;
12+
//! let kp1 = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng()));
13+
//! let public_key1 = kp1.public_key();
14+
//! # let kp2 = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng()));
15+
//! # let public_key2 = kp2.public_key();
1316
//! # let kp3 = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng()));
14-
//! # let p1_pubkey = kp1.public_key();
15-
//! # let p3_pubkey = kp3.public_key();
16-
//! # let my_keypair = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng()));
17-
//! # let _keylist = musig.new_keylist(vec![
18-
//! # Party::Local(kp1),
19-
//! # Party::Remote(my_keypair.public_key()),
20-
//! # Party::Local(kp3),
21-
//! # ]);
17+
//! # let public_key3 = kp3.public_key();
18+
//! // recieve the public keys of all other participants to form the aggregate key.
2219
//! let keylist = musig.new_keylist(vec![
23-
//! Party::Remote(p1_pubkey),
24-
//! Party::Local(my_keypair),
25-
//! Party::Remote(p3_pubkey),
20+
//! p1_public_key,
21+
//! p2_public_key,
22+
//! p3_public_key,
2623
//! ]);
27-
//! let message = Message::plain("my-app", b"chancellor on brink of second bailout for banks");
28-
//! // generate our aggregate key
2924
//! let agg_key = keylist.agg_public_key();
30-
//! // start a MuSig2 session by first exchanging nonces.
31-
//! // Since we're using deterministic nonces it's important we only use the session id once
32-
//! let my_nonces = musig.gen_nonces(&keylist, b"session-id-1337");
33-
//! // send this to the other parties
34-
//! let my_public_nonce = my_nonces[0].public();
35-
//! # let nonces = musig.gen_nonces(&_keylist, b"session-id-1337");
36-
//! # let p1_nonce = nonces[0].public();
37-
//! # let p3_nonce = nonces[1].public();
38-
//! # let mut _session = musig.start_sign_session_deterministic(&_keylist, my_nonces.iter().map(|n| n.public()), b"session-id-1337", message).unwrap();
39-
//! // Once you've got the nonces from the other two (p1_nonce and p3_nonce) you can start the signing session.
40-
//! let mut session = musig.start_sign_session(&keylist, my_nonces, [p1_nonce, p3_nonce], message).unwrap();
41-
//! // but since we're using deterministic nonce generation we can just remember the session id.
42-
//! // You should guarantee that this is not called ever again with the same session id!!!!
43-
//! let mut session = musig.start_sign_session_deterministic(&keylist, [p1_nonce, p3_nonce], b"session-id-1337", message).unwrap();
25+
//!
26+
//! // create unique nonce, and send public nonce to other parties
27+
//! let p1_nonce = musig.gen_nonces(&keypair.sk, &keylist, b"session-id-1337");
28+
//! let p1_public_nonce = p1_nonce.public;
29+
//! # let p2_nonce = musig.gen_nonces(&keypair.sk, &keylist, b"session-id-1337");
30+
//! # let p3_nonce = musig.gen_nonces(&keypair.sk, &keylist, b"session-id-1337");
31+
//! let nonces = vec![p1_public_nonce, p2_public_nonce, p3_public_nonce];
32+
//! // Once you've got the nonces from the other two (p2_nonce and p3_nonce) you can start the signing session.
33+
//! let message = Message::plain("my-app", b"chancellor on brink of second bailout for banks");
34+
//! let mut session = musig.start_sign_session(&keylist, nonces, message).unwrap();
4435
//! // sign with our (single) local keypair
45-
//! let my_sig = musig.sign_all(&keylist, &mut session)[0];
46-
//! # let _sigs = musig.sign_all(&_keylist, &mut _session);
47-
//! # let p1_sig = _sigs[0];
48-
//! # let p3_sig = _sigs[1];
36+
//! let p1_sig = musig.sign(&keylist, 0, kp1.sk, p1_nonce, &session);
37+
//! # let p2_sig = musig.sign(&keylist, 1, kp2.sk, p2_nonce, &session);
38+
//! # let p3_sig = musig.sign(&keylist, 2, kp3.sk, p3_nonce, &session);
4939
//! // receive p1_sig and p3_sig from somewhere and check they're valid
50-
//! assert!(musig.verify_partial_signature(&keylist, &session, 0, p1_sig));
40+
//! assert!(musig.verify_partial_signature(&keylist, &session, 1, p2_sig));
5141
//! assert!(musig.verify_partial_signature(&keylist, &session, 2, p3_sig));
5242
//! // combine them with ours into the final signature
53-
//! let sig = musig.combine_partial_signatures(&keylist, &session, [my_sig, p1_sig, p3_sig]);
43+
//! let sig = musig.combine_partial_signatures(&keylist, &session, [p1_sig, p2_sig, p3_sig]);
5444
//! // check it's a valid normal Schnorr signature
55-
//! musig.schnorr.verify(&keylist.agg_verification_key(), message, &sig);
45+
//! musig.schnorr.verify(&agg_key, message, &sig);
5646
//! ```
5747
//!
5848
//! ## Description
@@ -108,26 +98,6 @@ impl<H: Tagged, S: Default> Default for MuSig<H, S> {
10898
}
10999
}
110100

111-
impl<H: Tagged> MuSig<H, ()> {
112-
/// Creates a MuSig context that can only do key aggregation.
113-
///
114-
/// # Example
115-
///
116-
/// ```
117-
/// # use schnorr_fun::fun::{ XOnly };
118-
/// # let key1 = XOnly::random(&mut rand::thread_rng());
119-
/// # let key2 = XOnly::random(&mut rand::thread_rng());
120-
/// use schnorr_fun::musig::{MuSig, Party};
121-
/// use sha2::Sha256;
122-
/// let musig = MuSig::<Sha256>::keyagg_only();
123-
/// let keylist = musig.new_keylist(vec![Party::Remote(key1), Party::Remote(key2)]);
124-
/// println!("{:?}", keylist.agg_public_key())
125-
/// ```
126-
pub fn keyagg_only() -> Self {
127-
Self::_new(())
128-
}
129-
}
130-
131101
impl<H: Tagged, NG> MuSig<H, Schnorr<H, NG>> {
132102
/// Generate a new MuSig context from a Schnorr context.
133103
pub fn new(schnorr: Schnorr<H, NG>) -> Self {
@@ -150,8 +120,9 @@ pub struct KeyList {
150120
coefs: Vec<Scalar<Public>>,
151121
/// The aggregate key
152122
agg_key: Point<EvenY>,
153-
/// The
123+
/// The tweak on the aggregate key
154124
tweak: Scalar<Public, Zero>,
125+
/// Whether this aggregate key needs negation.
155126
needs_negation: bool,
156127
}
157128

@@ -169,17 +140,31 @@ impl KeyList {
169140
self.parties.iter().map(|xonly| *xonly)
170141
}
171142

172-
/// *Tweak* the aggregated key with a scalar so that the resulting key is equal to the existing
173-
/// key plus `tweak * G`. The tweak mutates the public key while still allowing the original set
174-
/// of signers to sign under the new key.
143+
/// Tweak the aggregate MuSig public key with a scalar so that the resulting key is equal to the
144+
/// existing key plus `tweak * G`. The tweak mutates the public key while still allowing
145+
/// the original set of signers to sign under the new key.
175146
///
176147
/// This is how you embed a taproot commitment into a key.
177148
///
149+
/// Also updates whether the MuSig KeyList needs negation.
150+
/// XOR of existing MuSig KeyList needs_negation and new tweaked key needs_negation.
151+
/// If both need negation, they will cancel out.
152+
///
153+
/// Public key
154+
/// X = (b*x) * G
155+
/// where b = 1 or -1
156+
/// For a tweak t: X' = X + t * G.
157+
/// If X' needs negation then we need secret
158+
/// -(b*x + t) = -b*x - t
159+
/// So new b = -b and t = -t.
160+
/// If X' doesn't need negation, leave b as is.
161+
/// i.e. previous needs_negation XOR new needs_negation.
162+
///
178163
/// ## Return value
179164
///
180-
/// Returns a new keylist with the same parties but a different aggregated public key. In the
181-
/// unusual case that the tweak is exactly equal to the negation of the aggregated secret key
182-
/// it returns `None`.
165+
/// Returns a new MuSig KeyList with the same parties but a different aggregated public key.
166+
/// In the erroneous case that the tweak is exactly equal to the negation of the aggregate
167+
/// secret key it returns `None`.
183168
pub fn tweak(&self, tweak: Scalar<impl Secrecy, impl ZeroChoice>) -> Option<Self> {
184169
let (agg_key, needs_negation) = g!(self.agg_key + tweak * G)
185170
.mark::<NonZero>()?
@@ -220,15 +205,15 @@ impl<H: Digest<OutputSize = U32> + Clone, S> MuSig<H, S> {
220205
/// use sha2::Sha256;
221206
/// let musig = MuSig::<Sha256, Schnorr<Sha256, Deterministic<Sha256>>>::default();
222207
/// let my_keypair = musig.schnorr.new_keypair(my_secret_key);
208+
/// let my_public_key = my_keypair.public_key();
223209
/// // Note the keys have to come in the same order on the other side!
224210
/// let keylist = musig.new_keylist(vec![
225-
/// Party::Local(my_keypair),
226-
/// Party::Remote(their_public_key),
211+
/// their_public_key,
212+
/// my_public_key,
227213
/// ]);
228214
/// ```
229215
pub fn new_keylist(&self, parties: Vec<XOnly>) -> KeyList {
230216
let keys = parties.clone();
231-
232217
let coeff_hash = {
233218
let L = self.pk_hash.clone().add(&keys[..]).finalize();
234219
self.coeff_hash.clone().add(L.as_slice())
@@ -267,6 +252,7 @@ impl<H: Digest<OutputSize = U32> + Clone, S> MuSig<H, S> {
267252
}
268253

269254
impl<H: Digest<OutputSize = U32> + Clone, NG: NonceGen> MuSig<H, Schnorr<H, NG>> {
255+
/// TODO
270256
/// Generate nonces for your local keys in keylist.
271257
///
272258
/// It is very important to carefully consider the implications of your choice of underlying
@@ -340,7 +326,7 @@ pub struct Adaptor {
340326
///
341327
/// ## Security
342328
///
343-
/// This struct has **secret nonces** in it up until you call [`clear_secrets`] or [`sign_all`]. If
329+
/// This struct has **secret nonces** in it up until you call [`clear_secrets`] or [`sign`]. If
344330
/// a malicious party gains access to it before and you generate a partial signature with this session they
345331
/// will be able to recover your secret key. If this is a concern simply avoid serializing this
346332
/// struct (until you've cleared it) and recreate it only when you need it.
@@ -358,7 +344,6 @@ pub struct Adaptor {
358344
pub struct SignSession<T = Ordinary> {
359345
b: Scalar<Public, Zero>,
360346
c: Scalar<Public, Zero>,
361-
// local_secret_nonce: NonceKeyPair,
362347
public_nonces: Vec<Nonce>,
363348
R: Point<EvenY>,
364349
nonce_needs_negation: bool,
@@ -368,8 +353,7 @@ pub struct SignSession<T = Ordinary> {
368353
impl<H: Digest<OutputSize = U32> + Clone, NG> MuSig<H, Schnorr<H, NG>> {
369354
/// Start a signing session.
370355
///
371-
/// You must provide you local secret nonces (the public portion must be shared with the other signer(s)).
372-
/// If you are using deterministic nonce generations it's possible to use [`start_sign_session_deterministic`] instead.
356+
/// You must provide the public nonces for this signing session in the correct order.
373357
///
374358
/// ## Return Value
375359
///
@@ -379,14 +363,10 @@ impl<H: Digest<OutputSize = U32> + Clone, NG> MuSig<H, Schnorr<H, NG>> {
379363
///
380364
/// # Panics
381365
///
382-
/// Panics if number of local or remote nonces passed in does not align with the parties in
383-
/// `keylist`.
384-
///
385-
/// [`start_sign_session_deterministic`]: Self::start_sign_session_deterministic
366+
/// Panics if number of nonces does not align with the parties in `keylist`.
386367
pub fn start_sign_session(
387368
&self,
388369
keylist: &KeyList,
389-
// local_secret_nonce: NonceKeyPair,
390370
nonces: Vec<Nonce>,
391371
message: Message<'_, Public>,
392372
) -> Option<SignSession> {
@@ -395,7 +375,6 @@ impl<H: Digest<OutputSize = U32> + Clone, NG> MuSig<H, Schnorr<H, NG>> {
395375
Some(SignSession {
396376
b,
397377
c,
398-
// local_secret_nonce,
399378
public_nonces,
400379
R,
401380
nonce_needs_negation,
@@ -492,24 +471,18 @@ impl<H: Digest<OutputSize = U32> + Clone, NG> MuSig<H, Schnorr<H, NG>> {
492471
R.0[1] = R.0[1].conditional_negate(r_needs_negation);
493472
}
494473

495-
// // let local_secret_nonce = local_nonce
496-
497-
// secret[0].conditional_negate(r_needs_negation);
498-
// secret[1].conditional_negate(r_needs_negation);
499-
500474
let c = self
501475
.schnorr
502476
.challenge(R.to_xonly(), keylist.agg_public_key(), message);
503477

504478
Some((b, c, Rs, R, r_needs_negation))
505479
}
506480

507-
/// Generates partial signatures (or partial encrypted signatures depending on `T`) under each of the `Local` entries in `keylist`.
508-
///
509-
/// The order of the partial signatures returned is the order of them in the keylist.
481+
/// Generates a partial signature (or partial encrypted signature depending on `T`) for the local_secret_nonce.
510482
///
483+
/// TODO
511484
/// This can only be called once per session as it clears the session (see also [`clear_secrets`]).
512-
/// Calling `sign_all` again will return an empty vector.
485+
/// Calling `sign` again will return an empty vector.
513486
///
514487
/// [`clear_secrets`]: SignSession::clear_secrets
515488
pub fn sign<T>(
@@ -659,7 +632,6 @@ mod test {
659632
keypair3.public_key(),
660633
]);
661634

662-
663635
for tweak in [tweak1, tweak2] {
664636
if let Some(tweak) = tweak {
665637
keylist = keylist.tweak(tweak).unwrap();
@@ -732,7 +704,6 @@ mod test {
732704
assert!(musig
733705
.schnorr
734706
.verify(&keylist.agg_verification_key(), message, &sig_p3));
735-
736707
}
737708
}
738709
}

0 commit comments

Comments
 (0)