Skip to content

Commit ea259cc

Browse files
committed
Add Musig2 example file
1 parent c6899b0 commit ea259cc

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

Cargo.toml

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

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

examples/musig.rs

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

0 commit comments

Comments
 (0)