Module schnorr_fun::musig
source · Expand description
The MuSig2 multisignature scheme.
§Synopsis
use rand_chacha::ChaCha20Rng;
use schnorr_fun::{musig, nonce::Deterministic, Message, Schnorr};
use sha2::Sha256;
// use sha256 with deterministic nonce generation -- be careful!
let musig = musig::new_with_deterministic_nonces::<sha2::Sha256>();
// use synthetic nonces with randomness from ThredRng -- harder to make a mistake.
let musig = musig::new_with_synthetic_nonces::<sha2::Sha256, rand::rngs::ThreadRng>();
// create a keypair
use schnorr_fun::fun::Scalar;
let my_keypair = musig.new_keypair(Scalar::random(&mut rand::thread_rng()));
let public_key1 = my_keypair.public_key();
// recieve the public keys of all other participants to form the aggregate key.
let agg_key = musig
.new_agg_key(vec![public_key1, public_key2, public_key3])
.into_xonly_key();
// create a unique nonce, and send the public nonce to other parties.
// ⚠ session_id must be different for every signing attempt
let session_id = b"signing-ominous-message-about-banks-attempt-1".as_slice();
let mut nonce_rng: ChaCha20Rng =
musig.seed_nonce_rng(&agg_key, &my_keypair.secret_key(), session_id);
let my_nonce = musig.gen_nonce(&mut nonce_rng);
let my_public_nonce = my_nonce.public();
// collect the public nonces from the other two parties
let nonces = vec![my_public_nonce, p2_public_nonce, p3_public_nonce];
let message = Message::plain("my-app", b"chancellor on brink of second bailout for banks");
// start the signing session
let session = musig.start_sign_session(&agg_key, nonces, message);
// sign with our single local keypair
let my_sig = musig.sign(&agg_key, &session, 0, &my_keypair, my_nonce);
// receive p2_sig and p3_sig from somewhere and check they're valid
assert!(musig.verify_partial_signature(&agg_key, &session, 1, p2_sig));
assert!(musig.verify_partial_signature(&agg_key, &session, 2, p3_sig));
// combine them with ours into the final signature
let sig = musig.combine_partial_signatures(&agg_key, &session, [my_sig, p2_sig, p3_sig]);
// check it's a valid normal Schnorr signature
musig
.schnorr
.verify(&agg_key.agg_public_key(), message, &sig);
§Description
The MuSig2 multisignature scheme lets you aggregate multiple public keys into a single public key that requires all of the corresponding secret keys to authorize a signature under the aggregate key.
See the excellent paper for the abstract details of the protocol and security proofs. ⚠ THIS IS EXPERIMENTAL⚠ it is currently compatible with this version of the specification.
⚠ THIS IS EXPERIMENTAL⚠ it is currently compatible with this PR to the specification. However, we go “off-spec” in a few places especially with regards to nonce generation where we provide our own APIs (that at the time of writing are subject to change).
Re-exports§
pub use crate::binonce::Nonce;
pub use crate::binonce::NonceKeyPair;
Structs§
- Marks the
SignSession
as being used to create an adaptor (a.k.a. one-time encrypted) signature. - A list of keys aggregated into a single key.
- The MuSig context.
- Marker type for indicating the
SignSession
is being used to create an ordinary Schnorr signature. - A signing session.
Functions§
- Constructor for a MuSig instance using deterministic nonce generation.
- Constructor for a MuSig instance using synthetic nonce generation.
- Create a MuSig instance which does not handle nonce generation.