|
9 | 9 | //! let musig = MuSig::<Sha256, Schnorr<Sha256, Deterministic<Sha256>>>::default(); |
10 | 10 | //! // create a keylist |
11 | 11 | //! use schnorr_fun::fun::Scalar; |
12 | | -//! let kp1 = musig |
| 12 | +//! let my_keypair = musig |
13 | 13 | //! .schnorr |
14 | 14 | //! .new_keypair(Scalar::random(&mut rand::thread_rng())); |
15 | | -//! let public_key1 = kp1.public_key(); |
| 15 | +//! let public_key1 = my_keypair.public_key(); |
16 | 16 | //! # let kp2 = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng())); |
17 | 17 | //! # let public_key2 = kp2.public_key(); |
18 | 18 | //! # let kp3 = musig.schnorr.new_keypair(Scalar::random(&mut rand::thread_rng())); |
|
22 | 22 | //! let agg_key = keylist.agg_public_key(); |
23 | 23 | //! |
24 | 24 | //! // create a unique nonce, and send the public nonce to other parties. |
25 | | -//! let p1_nonce = musig.gen_nonces(kp1.secret_key(), &keylist, b"session-id-1337"); |
26 | | -//! let p1_public_nonce = p1_nonce.public(); |
| 25 | +//! let my_nonce = musig.gen_nonces(my_keypair.secret_key(), &keylist, b"session-id-1337"); |
| 26 | +//! let my_public_nonce = my_nonce.public(); |
27 | 27 | //! # let p2_nonce = musig.gen_nonces(kp2.secret_key(), &keylist, b"session-id-1337"); |
28 | 28 | //! # let p2_public_nonce = p2_nonce.public(); |
29 | 29 | //! # let p3_nonce = musig.gen_nonces(kp3.secret_key(), &keylist, b"session-id-1337"); |
30 | 30 | //! # let p3_public_nonce = p3_nonce.public(); |
31 | 31 | //! // collect the public nonces from the other two parties |
32 | | -//! let nonces = vec![p1_public_nonce, p2_public_nonce, p3_public_nonce]; |
| 32 | +//! let nonces = vec![my_public_nonce, p2_public_nonce, p3_public_nonce]; |
33 | 33 | //! let message = Message::plain("my-app", b"chancellor on brink of second bailout for banks"); |
34 | 34 | //! // start the signing session |
35 | 35 | //! let session = musig.start_sign_session(&keylist, nonces, message).unwrap(); |
36 | 36 | //! // sign with our single local keypair |
37 | | -//! let p1_sig = musig.sign(&keylist, 0, kp1.secret_key(), p1_nonce, &session); |
| 37 | +//! let my_sig = musig.sign(&keylist, 0, my_keypair.secret_key(), my_nonce, &session); |
38 | 38 | //! # let p2_sig = musig.sign(&keylist, 1, kp2.secret_key(), p2_nonce, &session); |
39 | 39 | //! # let p3_sig = musig.sign(&keylist, 2, kp3.secret_key(), p3_nonce, &session); |
40 | | -//! // receive p1_sig and p3_sig from somewhere and check they're valid |
| 40 | +//! // receive p2_sig and p3_sig from somewhere and check they're valid |
41 | 41 | //! assert!(musig.verify_partial_signature(&keylist, &session, 1, p2_sig)); |
42 | 42 | //! assert!(musig.verify_partial_signature(&keylist, &session, 2, p3_sig)); |
43 | 43 | //! // combine them with ours into the final signature |
44 | | -//! let sig = musig.combine_partial_signatures(&keylist, &session, [p1_sig, p2_sig, p3_sig]); |
| 44 | +//! let sig = musig.combine_partial_signatures(&keylist, &session, [my_sig, p2_sig, p3_sig]); |
45 | 45 | //! // check it's a valid normal Schnorr signature |
46 | 46 | //! musig |
47 | 47 | //! .schnorr |
|
53 | 53 | //! The MuSig2 multisignature scheme lets you aggregate multiple public keys into a single public |
54 | 54 | //! key that requires all of the corresponding secret keys to authorize a signature under the aggregate key. |
55 | 55 | //! |
56 | | -//! This implementation is protocol compatible with the implementation merged into |
57 | | -//! [secp256k1-zkp]. |
| 56 | +//! See [the excellent paper] for the abstract details of the protocol and security proofs. |
| 57 | +//! **⚠ THIS IS EXPERIMENTAL AND NOT COMPATIBLE WITH THE [DRAFT SPECIFICATION](https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki) ⚠** |
58 | 58 | //! |
59 | | -//! See [the excellent paper] for the abstract details of the protocol. |
60 | 59 | //! |
61 | 60 | //! [the excellent paper]: https://eprint.iacr.org/2020/1261.pdf |
62 | 61 | //! [secp256k1-zkp]: https://github.com/ElementsProject/secp256k1-zkp/pull/131 |
@@ -148,26 +147,6 @@ impl KeyList { |
148 | 147 | /// the original set of signers to sign under the new key. |
149 | 148 | /// |
150 | 149 | /// This is how you embed a taproot commitment into a key. |
151 | | - /// |
152 | | - /// Also updates whether the MuSig KeyList needs negation. |
153 | | - /// XOR of existing MuSig KeyList needs_negation and new tweaked key needs_negation. |
154 | | - /// If both need negation, they will cancel out. |
155 | | - /// |
156 | | - /// Public key |
157 | | - /// X = (b*x) * G |
158 | | - /// where b = 1 or -1 |
159 | | - /// For a tweak t: X' = X + t * G. |
160 | | - /// If X' needs negation then we need secret |
161 | | - /// -(b*x + t) = -b*x - t |
162 | | - /// So new b = -b and t = -t. |
163 | | - /// If X' doesn't need negation, leave b as is. |
164 | | - /// i.e. previous needs_negation XOR new needs_negation. |
165 | | - /// |
166 | | - /// ## Return value |
167 | | - /// |
168 | | - /// Returns a new MuSig KeyList with the same parties but a different aggregated public key. |
169 | | - /// In the erroneous case that the tweak is exactly equal to the negation of the aggregate |
170 | | - /// secret key it returns `None`. |
171 | 150 | pub fn tweak(&self, tweak: Scalar<impl Secrecy, impl ZeroChoice>) -> Option<Self> { |
172 | 151 | let (agg_key, needs_negation) = g!(self.agg_key + tweak * G) |
173 | 152 | .mark::<NonZero>()? |
|
0 commit comments