|
| 1 | +extern crate secp256k1; |
| 2 | + |
| 3 | +use secp256k1::musig::{ |
| 4 | + new_musig_nonce_pair, MusigAggNonce, MusigKeyAggCache, MusigPartialSignature, MusigPubNonce, |
| 5 | + MusigSession, MusigSessionId, |
| 6 | +}; |
| 7 | +use secp256k1::{Keypair, Message, PublicKey, Scalar, Secp256k1, SecretKey}; |
| 8 | + |
| 9 | +fn main() { |
| 10 | + let secp = Secp256k1::new(); |
| 11 | + let mut rng = rand::thread_rng(); |
| 12 | + |
| 13 | + let (seckey1, pubkey1) = secp.generate_keypair(&mut rng); |
| 14 | + |
| 15 | + let seckey2 = SecretKey::new(&mut rng); |
| 16 | + let pubkey2 = PublicKey::from_secret_key(&secp, &seckey2); |
| 17 | + |
| 18 | + let pubkeys = [pubkey1, pubkey2]; |
| 19 | + let pubkeys_ref: Vec<&PublicKey> = pubkeys.iter().collect(); |
| 20 | + let pubkeys_ref = pubkeys_ref.as_slice(); |
| 21 | + |
| 22 | + let mut musig_key_agg_cache = MusigKeyAggCache::new(&secp, pubkeys_ref); |
| 23 | + |
| 24 | + let plain_tweak: [u8; 32] = *b"this could be a BIP32 tweak....\0"; |
| 25 | + let xonly_tweak: [u8; 32] = *b"this could be a Taproot tweak..\0"; |
| 26 | + |
| 27 | + let plain_tweak = Scalar::from_be_bytes(plain_tweak).unwrap(); |
| 28 | + musig_key_agg_cache.pubkey_ec_tweak_add(&secp, &plain_tweak).unwrap(); |
| 29 | + |
| 30 | + let xonly_tweak = Scalar::from_be_bytes(xonly_tweak).unwrap(); |
| 31 | + let tweaked_agg_pk = musig_key_agg_cache.pubkey_xonly_tweak_add(&secp, &xonly_tweak).unwrap(); |
| 32 | + |
| 33 | + let agg_pk = musig_key_agg_cache.agg_pk(); |
| 34 | + |
| 35 | + assert_eq!(agg_pk, tweaked_agg_pk.x_only_public_key().0); |
| 36 | + |
| 37 | + let msg_bytes: [u8; 32] = *b"this_could_be_the_hash_of_a_msg!"; |
| 38 | + let msg = Message::from_digest_slice(&msg_bytes).unwrap(); |
| 39 | + |
| 40 | + let musig_session_id1 = MusigSessionId::new(&mut rng); |
| 41 | + |
| 42 | + let nonce_pair1 = new_musig_nonce_pair( |
| 43 | + &secp, |
| 44 | + musig_session_id1, |
| 45 | + Some(&musig_key_agg_cache), |
| 46 | + Some(seckey1), |
| 47 | + pubkey1, |
| 48 | + Some(msg), |
| 49 | + None, |
| 50 | + ) |
| 51 | + .unwrap(); |
| 52 | + |
| 53 | + let musig_session_id2 = MusigSessionId::new(&mut rng); |
| 54 | + |
| 55 | + let nonce_pair2 = new_musig_nonce_pair( |
| 56 | + &secp, |
| 57 | + musig_session_id2, |
| 58 | + Some(&musig_key_agg_cache), |
| 59 | + Some(seckey2), |
| 60 | + pubkey2, |
| 61 | + Some(msg), |
| 62 | + None, |
| 63 | + ) |
| 64 | + .unwrap(); |
| 65 | + |
| 66 | + let sec_nonce1 = nonce_pair1.0; |
| 67 | + let pub_nonce1 = nonce_pair1.1; |
| 68 | + |
| 69 | + let sec_nonce2 = nonce_pair2.0; |
| 70 | + let pub_nonce2 = nonce_pair2.1; |
| 71 | + |
| 72 | + let nonces = [pub_nonce1, pub_nonce2]; |
| 73 | + let nonces_ref: Vec<&MusigPubNonce> = nonces.iter().collect(); |
| 74 | + let nonces_ref = nonces_ref.as_slice(); |
| 75 | + |
| 76 | + let agg_nonce = MusigAggNonce::new(&secp, nonces_ref); |
| 77 | + |
| 78 | + let session = MusigSession::new(&secp, &musig_key_agg_cache, agg_nonce, msg); |
| 79 | + |
| 80 | + let keypair1 = Keypair::from_secret_key(&secp, &seckey1); |
| 81 | + let partial_sign1 = |
| 82 | + session.partial_sign(&secp, sec_nonce1, &keypair1, &musig_key_agg_cache).unwrap(); |
| 83 | + |
| 84 | + let keypair2 = Keypair::from_secret_key(&secp, &seckey2); |
| 85 | + let partial_sign2 = |
| 86 | + session.partial_sign(&secp, sec_nonce2, &keypair2, &musig_key_agg_cache).unwrap(); |
| 87 | + |
| 88 | + let is_partial_signature_valid = |
| 89 | + session.partial_verify(&secp, &musig_key_agg_cache, partial_sign1, pub_nonce1, pubkey1); |
| 90 | + assert!(is_partial_signature_valid); |
| 91 | + |
| 92 | + let is_partial_signature_valid = |
| 93 | + session.partial_verify(&secp, &musig_key_agg_cache, partial_sign2, pub_nonce2, pubkey2); |
| 94 | + assert!(is_partial_signature_valid); |
| 95 | + |
| 96 | + let partial_sigs = [partial_sign1, partial_sign2]; |
| 97 | + let partial_sigs_ref: Vec<&MusigPartialSignature> = partial_sigs.iter().collect(); |
| 98 | + let partial_sigs_ref = partial_sigs_ref.as_slice(); |
| 99 | + |
| 100 | + let sig64 = session.partial_sig_agg(partial_sigs_ref); |
| 101 | + |
| 102 | + assert!(secp.verify_schnorr(&sig64, &msg_bytes, &agg_pk).is_ok()); |
| 103 | +} |
0 commit comments