Skip to content

Instantly share code, notes, and snippets.

@rot13maxi
Created June 4, 2023 20:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rot13maxi/f6761dc7129b0b6f395445b4df83a383 to your computer and use it in GitHub Desktop.
Save rot13maxi/f6761dc7129b0b6f395445b4df83a383 to your computer and use it in GitHub Desktop.
adaptor fun
use rand_chacha::ChaCha20Rng;
use schnorr_fun::fun::{KeyPair, Scalar};
use schnorr_fun::{Message, nonce, Schnorr};
use schnorr_fun::adaptor::Adaptor;
use schnorr_fun::fun::marker::Public;
use schnorr_fun::musig::MuSig;
use sha2::Sha256;
fn main() {
// Little proof of concept. Doesn't actually do real transactions, but you get the idea.
// Alice and Bob want to do a coin swap.
// Alice wants to send one bitcoin to Bob and Bob wants to send one bitcoin to Alice.
// They want to do this without trusting each other.
// Alice generates two public keys and Bob generates one public key and an encryption key.
// They generate two shared keys, one for each transaction.
// They sign transactions that spend from the shared keys, and encrypt the signatures with the encryption key.
// Once bob has both encrypted signatures, he can decrypt his signature and use it to spend from the shared key.
// Once Alice sees that Bob has spent from the shared key, she can decrypt her signature and use it to spend from the shared key.
let alice_secretkey1 = Scalar::random(&mut rand::thread_rng());
let alice_secretkey2 = Scalar::random(&mut rand::thread_rng());
let bob_secretkey = Scalar::random(&mut rand::thread_rng());
let schnorr = Schnorr::<Sha256, nonce::Deterministic<Sha256>>::default();
let musig = MuSig::new(schnorr);
let alice_keypair1 = musig.new_keypair(alice_secretkey1);
let alice_keypair2 = musig.new_keypair(alice_secretkey2);
let bob_keypair = musig.new_keypair(bob_secretkey);
let bob_decryption_key = Scalar::random(&mut rand::thread_rng());
let bob_encryption_key = musig.schnorr.encryption_key_for(&bob_decryption_key);
let agg_key1 = musig.new_agg_key(vec![alice_keypair1.public_key(), bob_keypair.public_key()]).into_xonly_key();
let agg_key2 = musig.new_agg_key(vec![alice_keypair2.public_key(), bob_keypair.public_key()]).into_xonly_key();
let message1 = Message::<Public>::plain("test-bitcoin", b"Send one bitcoin from alice to bob");
let message2 = Message::<Public>::plain("test-bitcoin", b"Send one bitcoin from bob to alice");
let session1_id = message1.bytes.into();
let session2_id = message2.bytes.into();
let mut nonce_rng1: ChaCha20Rng = musig.seed_nonce_rng(&agg_key1, &alice_keypair1.secret_key(), session1_id);
let mut nonce_rng2: ChaCha20Rng = musig.seed_nonce_rng(&agg_key2, &alice_keypair2.secret_key(), session2_id);
let alice_nonce1 = musig.gen_nonce(&mut nonce_rng1);
let alice_nonce2 = musig.gen_nonce(&mut nonce_rng2);
let bob_nonce1 = musig.gen_nonce(&mut nonce_rng1);
let bob_nonce2 = musig.gen_nonce(&mut nonce_rng2);
let nonces1 = vec![alice_nonce1.public, bob_nonce1.public];
let nonces2 = vec![alice_nonce2.public, bob_nonce2.public];
let alice_session1 = musig
.start_encrypted_sign_session(
&agg_key1,
nonces1.clone(),
message1,
&bob_encryption_key
).unwrap();
let alice_session2 = musig
.start_encrypted_sign_session(
&agg_key2,
nonces2.clone(),
message2,
&bob_encryption_key
).unwrap();
let bob_session1 = musig
.start_encrypted_sign_session(
&agg_key1,
nonces1.clone(),
message1,
&bob_encryption_key
).unwrap();
let bob_session2 = musig
.start_encrypted_sign_session(
&agg_key2,
nonces2.clone(),
message2,
&bob_encryption_key
).unwrap();
let alice_sig1 = musig.sign(&agg_key1, &alice_session1, 0, &alice_keypair1, alice_nonce1);
let alice_sig2 = musig.sign(&agg_key2, &alice_session2, 0, &alice_keypair2, alice_nonce2);
let bob_sig1 = musig.sign(&agg_key1, &bob_session1, 1, &bob_keypair, bob_nonce1);
let bob_sig2 = musig.sign(&agg_key2, &bob_session2, 1, &bob_keypair, bob_nonce2);
assert!(musig.verify_partial_signature(&agg_key1, &alice_session1, 0, alice_sig1.clone()));
assert!(musig.verify_partial_signature(&agg_key2, &alice_session2, 0, alice_sig2.clone()));
assert!(musig.verify_partial_signature(&agg_key1, &bob_session1, 1, bob_sig1.clone()));
assert!(musig.verify_partial_signature(&agg_key2, &bob_session2, 1, bob_sig2.clone()));
let partial_sigs1 = vec![alice_sig1, bob_sig1];
let partial_sigs2 = vec![alice_sig2, bob_sig2];
let combined_sig1 = musig.combine_partial_encrypted_signatures(&agg_key1, &alice_session1, partial_sigs1.clone());
let combined_sig2 = musig.combine_partial_encrypted_signatures(&agg_key2, &alice_session2, partial_sigs2.clone());
let decrypted_sig1 = musig.schnorr.decrypt_signature(bob_decryption_key.clone(), combined_sig1.clone());
let recovered_key = musig.schnorr.recover_decryption_key(&bob_encryption_key, &combined_sig1, &decrypted_sig1).unwrap();
let decrypted_sig2 = musig.schnorr.decrypt_signature(recovered_key, combined_sig2.clone());
assert!(musig.schnorr.verify(&agg_key2.agg_public_key(), message2, &decrypted_sig2));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment