Skip to content

Commit 97fb6d1

Browse files
committed
Add Musig2 example file
1 parent 3e9d296 commit 97fb6d1

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-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

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
extern crate secp256k1;
2+
3+
use secp256k1::musig::{
4+
new_nonce_pair, AggregatedNonce, KeyAggCache, PartialSignature, PublicNonce,
5+
Session, SessionSecretRand,
6+
};
7+
use secp256k1::{Keypair, Message, PublicKey, Scalar, Secp256k1, SecretKey, pubkey_sort};
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 mut pubkeys_ref: Vec<&PublicKey> = pubkeys.iter().collect();
20+
let pubkeys_ref = pubkeys_ref.as_mut_slice();
21+
22+
pubkey_sort(&secp, pubkeys_ref);
23+
24+
let mut musig_key_agg_cache = KeyAggCache::new(&secp, pubkeys_ref);
25+
26+
let plain_tweak: [u8; 32] = *b"this could be a BIP32 tweak....\0";
27+
let xonly_tweak: [u8; 32] = *b"this could be a Taproot tweak..\0";
28+
29+
let plain_tweak = Scalar::from_be_bytes(plain_tweak).unwrap();
30+
musig_key_agg_cache.pubkey_ec_tweak_add(&secp, &plain_tweak).unwrap();
31+
32+
let xonly_tweak = Scalar::from_be_bytes(xonly_tweak).unwrap();
33+
let tweaked_agg_pk = musig_key_agg_cache.pubkey_xonly_tweak_add(&secp, &xonly_tweak).unwrap();
34+
35+
let agg_pk = musig_key_agg_cache.agg_pk();
36+
37+
assert_eq!(agg_pk, tweaked_agg_pk.x_only_public_key().0);
38+
39+
let msg_bytes: [u8; 32] = *b"this_could_be_the_hash_of_a_msg!";
40+
let msg = Message::from_digest_slice(&msg_bytes).unwrap();
41+
42+
let musig_session_sec_rand1 = SessionSecretRand::from_rng(&mut rng);
43+
44+
let nonce_pair1 = new_nonce_pair(
45+
&secp,
46+
musig_session_sec_rand1,
47+
Some(&musig_key_agg_cache),
48+
Some(seckey1),
49+
pubkey1,
50+
Some(msg),
51+
None,
52+
);
53+
54+
let musig_session_sec_rand2 = SessionSecretRand::from_rng(&mut rng);
55+
56+
let nonce_pair2 = new_nonce_pair(
57+
&secp,
58+
musig_session_sec_rand2,
59+
Some(&musig_key_agg_cache),
60+
Some(seckey2),
61+
pubkey2,
62+
Some(msg),
63+
None,
64+
);
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<&PublicNonce> = nonces.iter().collect();
74+
let nonces_ref = nonces_ref.as_slice();
75+
76+
let agg_nonce = AggregatedNonce::new(&secp, nonces_ref);
77+
78+
let session = Session::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);
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);
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<&PartialSignature> = partial_sigs.iter().collect();
98+
let partial_sigs_ref = partial_sigs_ref.as_slice();
99+
100+
let aggregated_signature = session.partial_sig_agg(partial_sigs_ref);
101+
102+
assert!(aggregated_signature.verify(&secp, &agg_pk, &msg_bytes).is_ok());
103+
}

0 commit comments

Comments
 (0)