Skip to content

Commit 447a94c

Browse files
committed
Add Musig2 example file
1 parent c2f20b8 commit 447a94c

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ required-features = ["hashes", "std"]
6565
name = "generate_keys"
6666
required-features = ["rand", "std"]
6767

68+
[[example]]
69+
name = "musig"
70+
required-features = ["rand", "std"]
71+
6872
[workspace]
6973
members = ["secp256k1-sys"]
7074
exclude = ["no_std_test"]

examples/musig.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
extern crate secp256k1;
2+
3+
use secp256k1::{Keypair, Message, PublicKey, Scalar, Secp256k1, SecretKey };
4+
use secp256k1::musig::{MusigKeyAggCache, MusigSessionId, new_musig_nonce_pair, MusigAggNonce, MusigSession};
5+
6+
fn main() {
7+
8+
let secp = Secp256k1::new();
9+
let mut rng = rand::thread_rng();
10+
11+
let (seckey1, pubkey1) = secp.generate_keypair(&mut rng);
12+
13+
assert_eq!(pubkey1, PublicKey::from_secret_key(&secp, &seckey1));
14+
15+
let seckey2 = SecretKey::new(&mut rng);
16+
let pubkey2 = PublicKey::from_secret_key(&secp, &seckey2);
17+
18+
assert_eq!(pubkey2, PublicKey::from_secret_key(&secp, &seckey2));
19+
20+
let pubkeys = [pubkey1, pubkey2];
21+
22+
let mut musig_key_agg_cache = MusigKeyAggCache::new(&secp, &pubkeys);
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 =
43+
new_musig_nonce_pair(&secp, musig_session_id1, Some(&musig_key_agg_cache), Some(seckey1), pubkey1, Some(msg), None).unwrap();
44+
45+
let musig_session_id2 = MusigSessionId::new(&mut rng);
46+
47+
let nonce_pair2 =
48+
new_musig_nonce_pair(&secp, musig_session_id2, Some(&musig_key_agg_cache), Some(seckey2), pubkey2, Some(msg), None).unwrap();
49+
50+
let sec_nonce1 = nonce_pair1.0;
51+
let pub_nonce1 = nonce_pair1.1;
52+
53+
let sec_nonce2 = nonce_pair2.0;
54+
let pub_nonce2 = nonce_pair2.1;
55+
56+
let nonces = [pub_nonce1, pub_nonce2];
57+
58+
let agg_nonce = MusigAggNonce::new(&secp, &nonces);
59+
60+
let session = MusigSession::new(&secp, &musig_key_agg_cache, agg_nonce, msg);
61+
62+
let keypair1 = Keypair::from_secret_key(&secp, &seckey1);
63+
let partial_sign1 = session.partial_sign(&secp, sec_nonce1, &keypair1, &musig_key_agg_cache).unwrap();
64+
65+
let keypair2 = Keypair::from_secret_key(&secp, &seckey2);
66+
let partial_sign2 = session.partial_sign(&secp, sec_nonce2, &keypair2, &musig_key_agg_cache).unwrap();
67+
68+
let is_partial_signature_valid = session.partial_verify(&secp, &musig_key_agg_cache, partial_sign1, pub_nonce1, pubkey1);
69+
assert!(is_partial_signature_valid);
70+
71+
let is_partial_signature_valid = session.partial_verify(&secp, &musig_key_agg_cache, partial_sign2, pub_nonce2, pubkey2);
72+
assert!(is_partial_signature_valid);
73+
74+
let partial_sigs = [partial_sign1, partial_sign2];
75+
76+
let sig64 = session.partial_sig_agg(&partial_sigs);
77+
78+
assert!(secp.verify_schnorr(&sig64, &msg_bytes, &agg_pk).is_ok());
79+
}

0 commit comments

Comments
 (0)