Created
June 4, 2023 20:31
-
-
Save rot13maxi/f6761dc7129b0b6f395445b4df83a383 to your computer and use it in GitHub Desktop.
adaptor fun
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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