• Home
  • About Us
  • disclaimer
  • Privacy Policy
  • Terms and Conditions
  • Contact Us
Crypto News
  • Home
  • Crypto News
  • Team Portofolio (Premium)
  • Member Login
No Result
View All Result
  • Home
  • Crypto News
  • Team Portofolio (Premium)
  • Member Login
No Result
View All Result
Crypto News
No Result
View All Result
Home Crypto News

taproot – Musig signature validation mismatch

Cryptoadmin by Cryptoadmin
September 4, 2024
in Crypto News
0
BEST CRYPTO RECOVERY FIRM 2024
189
SHARES
1.5k
VIEWS
Share on FacebookShare on Twitter


I am attempting to grasp the primitives of Taproot and Musig2 so I can implement them into my software. I am utilizing the rust-bitcoin library and have written a script to create a Taproot tackle from an aggregated Musig2 public key (i’ve funded it with sats on mutinynet), create a tx spending from it & signal it, confirm the signature, after which spend the tx. Nevertheless, I am getting the error mandatory-script-verify-flag-failed (Invalid Schnorr signature) when I attempt to spend the tx. The odd factor is that the in-script sig validation throws no points.

Right here is the related code:


use bitcoin::consensus::Encodable;

use bitcoin::hashes::Hash;
use bitcoin::key::{Keypair, UntweakedPublicKey};
use bitcoin::locktime::absolute;

use bitcoin::secp256k1::{rand, Message, Secp256k1, SecretKey, Verification};
use bitcoin::sighash::{Prevouts, SighashCache, TapSighashType};
use bitcoin::{
    transaction, Handle, Quantity, Community, OutPoint, PublicKey, ScriptBuf, Sequence, Transaction,
    TxIn, TxOut, Txid, Witness, XOnlyPublicKey,
};
use musig2::secp::Level;
use musig2::{
    aggregate_partial_signatures, sign_partial, verify_single, AggNonce, BinaryEncoding,
    KeyAggContext, PubNonce, SecNonce,
};
use rand::thread_rng;

use std::str::FromStr;

const DUMMY_UTXO_AMOUNT: u64 = 100000;
const SPEND_AMOUNT: u64 = 90000;
const SK: &str = "e504905952697837ac0f0dc9e46deb0340ae6468b185ba79e4fa96ebda3964c2";
const SK2: &str = "6bb7bc5dd0c9db0ca8bdba4616ee92afceb432551e0f23b32ea7bcada18da696";
const SK3: &str = "57d44ecb8812680e871732233ed8e4d4e11a25f22aef6c81dbe35a424ad8db41";
const TXID: &str = "726499fb478422087e7a89a04f25de5ed98e87c9881e4a264e8f31143cdee17b";
const VOUT: u32 = 1;

fn most important() {
    let keypair_array = vec![
        Keypair::from_secret_key(&Secp256k1::new(), &SecretKey::from_str(SK).unwrap()),
        Keypair::from_secret_key(&Secp256k1::new(), &SecretKey::from_str(SK2).unwrap()),
        Keypair::from_secret_key(&Secp256k1::new(), &SecretKey::from_str(SK3).unwrap()),
    ];

    let begin = std::time::Prompt::now();
    let tx = construct_refund_transaction(
        TXID,
        VOUT,
        DUMMY_UTXO_AMOUNT,
        SPEND_AMOUNT,
        "tb1p6e4q26tvyc7dmxfnk5zzhkux9d6pqpn0k5qxlw4gvc90unc0m3rq93a0tl",
        keypair_array,
    );
    let period = begin.elapsed();

    println!("Time taken to assemble refund transaction: {:?}", period);

    match tx {
        Okay(hex) => {
            post_tx(hex);
        }
        Err(e) => {
            println!("Error setting up transaction: {:?}", e);
        }
    }
}

pub fn construct_refund_transaction(
    from_txid: &str,
    from_vout: u32,
    from_amount: u64,
    spend_amount: u64,
    to_address: &str,
    keypair_array: Vec<Keypair>,
) -> End result<String, Field<dyn std::error::Error>> {
    // Step 1: Convert public keys to factors for MuSig2
    let points_vec: Vec<Level> = keypair_array
        .iter()
        .map(|keypair| Level::from_hex(&keypair.public_key().to_string()).unwrap())
        .gather();

    // Step 2: Create a KeyAggContext for MuSig2
    let context = KeyAggContext::new(points_vec).unwrap();

    // Step 3: Get the aggregated public key
    let agg_pubkey: [u8; 33] = context.aggregated_pubkey();
    // println!("Combination pubkey: {:?}", hex::encode(agg_pubkey));

    // Step 4: Create a P2TR tackle from the aggregated public key
    let pubkey = PublicKey::from_slice(&agg_pubkey).unwrap();
    let xonly_pubkey = XOnlyPublicKey::from(pubkey);
    let secp = Secp256k1::new();
    // let tackle = Handle::p2tr(&secp, xonly_pubkey, None, Community::Signet);
    // println!("P2TR tackle: {}", tackle);

    // Step 5: Get the unspent transaction output (UTXO)
    let (out_point, utxo) = unspent_transaction_output(
        &secp,
        xonly_pubkey,
        Txid::from_str(from_txid).unwrap(),
        from_vout,
        from_amount,
    );

    // Step 6: Get the receiver's tackle
    let tackle = receivers_address(to_address);

    // Step 7: Create the transaction enter
    let enter = TxIn {
        previous_output: out_point,
        script_sig: ScriptBuf::default(), // Empty for P2TR
        sequence: Sequence::ENABLE_RBF_NO_LOCKTIME,
        witness: Witness::default(), // Might be stuffed after signing
    };

    // Step 8: Create the transaction output
    let spend = TxOut {
        worth: Quantity::from_sat(spend_amount),
        script_pubkey: tackle.script_pubkey(),
    };

    // Step 9: Assemble the unsigned transaction
    let mut unsigned_tx = Transaction {
        model: transaction::Model::TWO,
        lock_time: absolute::LockTime::ZERO,
        enter: vec![input],
        output: vec![spend],
    };
    let input_index = 0;

    // Step 10: Put together for signing
    let sighash_type = TapSighashType::Default;
    let prevouts = vec![utxo];
    let prevouts = Prevouts::All(&prevouts);

    // Step 11: Calculate the sighash
    let mut sighasher = SighashCache::new(&mut unsigned_tx);
    let sighash = sighasher
        .taproot_key_spend_signature_hash(input_index, &prevouts, sighash_type)
        .count on("didn't assemble sighash");

    // Step 12: Put together the message to be signed
    let msg = Message::from_digest(sighash.to_byte_array());

    // Step 13: Generate random nonces for MuSig2
    let mut rng = thread_rng();
    let n = keypair_array.len();
    let secret_nonces: Vec<SecNonce> = (0..n).map(|_| SecNonce::random(&mut rng)).gather();
    let public_nonces: Vec<PubNonce> = secret_nonces.iter().map(|sn| sn.public_nonce()).gather();

    // Step 14: Combination nonces
    let agg_nonce = AggNonce::sum(&public_nonces);

    // Step 15: Generate partial signatures
    let mut partial_sigs = Vec::new();
    for (i, keypair) in keypair_array.iter().enumerate() {
        let seckey =
            musig2::secp::Scalar::from_slice(&keypair.secret_key().secret_bytes()).unwrap();
        let partial_sig: musig2::PartialSignature = sign_partial(
            &context,
            seckey,
            secret_nonces[i].clone(),
            &agg_nonce,
            msg.as_ref(),
        )
        .unwrap();
        partial_sigs.push(partial_sig);
        // println!("Partial signature {}: {:?}", i, partial_sig);
    }

    // Step 16: Combination partial signatures
    let aggregated_signature: musig2::CompactSignature =
        aggregate_partial_signatures(&context, &agg_nonce, partial_sigs, msg.as_ref()).unwrap();
    // println!("Aggregated signature: {:?}", aggregated_signature);

    // Step 17: Confirm the aggregated signature
    let verification_result = verify_single(
        Level::from_slice(&agg_pubkey).unwrap(),
        aggregated_signature,
        msg.as_ref(),
    );

    match verification_result {
        Okay(()) => println!("Signature is legitimate"),
        Err(e) => println!("Signature verification failed: {:?}", e),
    }

    // Step 18: Add the signature to the transaction witness
    sighasher
        .witness_mut(input_index)
        .unwrap()
        .push(&aggregated_signature.to_bytes());

    // Step 19: Finalize the signed transaction
    let tx = sighasher.into_transaction();

    // Step 20: Serialize and print the signed transaction
    let mut serialized = Vec::new();
    tx.consensus_encode(&mut serialized).unwrap();
    let hex = serialized.as_hex();
    // println!("Transaction hex: {}", hex);

    Okay(hex.to_string())
}

// Helper operate to parse and validate the receiver's tackle
fn receivers_address(tackle: &str) -> Handle {
    tackle
        .parse::<Handle<_>>()
        .count on("a legitimate tackle")
        .require_network(Community::Signet)
        .count on("legitimate tackle for signet")
}

// Helper operate to create an unspent transaction output (UTXO)
fn unspent_transaction_output<C: Verification>(
    secp: &Secp256k1<C>,
    internal_key: UntweakedPublicKey,
    txid: Txid,
    vout: u32,
    quantity: u64,
) -> (OutPoint, TxOut) {
    let script_pubkey = ScriptBuf::new_p2tr(secp, internal_key, None);
    let out_point = OutPoint { txid, vout };
    let utxo = TxOut {
        worth: Quantity::from_sat(quantity),
        script_pubkey,
    };
    (out_point, utxo)
}

fn post_tx(hex: String) {
    let shopper = reqwest::blocking::Consumer::new();
    let res = shopper.submit("https://mutinynet.com/api/tx").physique(hex).ship();

    match res {
        Okay(res) => {
            if res.standing().is_success() {
                println!("Response: {:?}", res.textual content());
            } else {
                let error_text = res.textual content().unwrap_or_default();
                if let Some(message) = error_text.break up("message":"").nth(1) {
                    if let Some(error_message) = message.break up(""").subsequent() {
                        println!("Error: {}", error_message);
                    } else {
                        println!("Error: {}", error_text);
                    }
                } else {
                    println!("Error: {}", error_text);
                }
            }
        }
        Err(e) => {
            println!("Error sending request: {:?}", e);
        }
    }
}

Am I doing something blatantly mistaken?

(these are dummy SKs I generated for the aim of this take a look at)

Tags: mismatchMusigsignaturetaprootvalidation
Share76Tweet47
  • Trending
  • Comments
  • Latest
PURA Cost Processing | CoinPayments

PURA Cost Processing | CoinPayments

May 13, 2024
How Essential is Jito Solana MEV Bot Growth for the Cryptocurrency Ecosystem?

How Essential is Jito Solana MEV Bot Growth for the Cryptocurrency Ecosystem?

July 31, 2024
The Sandbox Basic Evaluation – Metaverse Crypto Gaming Platform

The Sandbox Basic Evaluation – Metaverse Crypto Gaming Platform

March 2, 2024
Arkham Alternate Lists MELANIA for Spot and Perpetual Buying and selling

Arkham Alternate Lists MELANIA for Spot and Perpetual Buying and selling

January 26, 2025
Ethiopia to begin mining Bitcoin by means of new information mining partnership

Ethiopia to begin mining Bitcoin by means of new information mining partnership

0
Be part of HitBTC official social media channels !

Be part of HitBTC official social media channels !

0
Bitwise launching spot bitcoin ETF (BITB) – CryptoNinjas

Bitwise launching spot bitcoin ETF (BITB) – CryptoNinjas

0
DeFi Masterclass. Decentralized Finance (DeFi) is an… | by Rohas Nagpal | Blockchain Weblog

DeFi Masterclass. Decentralized Finance (DeFi) is an… | by Rohas Nagpal | Blockchain Weblog

0
Can Bitcoin Worth Bounce To $120,000 Or Will It Break Beneath $100,000?

Can Bitcoin Worth Bounce To $120,000 Or Will It Break Beneath $100,000?

June 7, 2025
Solana (SOL) Introduces Alpenglow for Sooner Blockchain Consensus

Solana (SOL) Introduces Alpenglow for Sooner Blockchain Consensus

June 7, 2025
UK to Think about Lifting Ban on Retail Entry to Crypto Alternate-Traded Notes

UK to Think about Lifting Ban on Retail Entry to Crypto Alternate-Traded Notes

June 7, 2025
TakeOver Efficiently Hosts Second Annual BitGala Celebrating Bitcoin In Las Vegas

TakeOver Efficiently Hosts Second Annual BitGala Celebrating Bitcoin In Las Vegas

June 6, 2025

About Us

Welcome to Blog.cryptostudy.net The goal of Blog.cryptostudy.net is to give you the absolute best news sources for any topic! Our topics are carefully curated and constantly updated as we know the web moves fast so we try to as well.

Recent Posts

  • Can Bitcoin Worth Bounce To $120,000 Or Will It Break Beneath $100,000?
  • Solana (SOL) Introduces Alpenglow for Sooner Blockchain Consensus
  • UK to Think about Lifting Ban on Retail Entry to Crypto Alternate-Traded Notes
  • Home
  • About Us
  • disclaimer
  • Privacy Policy
  • Terms and Conditions
  • Contact Us

Copyright © 2024 Blog.cryptostudy.net | All Rights Reserved.

No Result
View All Result
  • Home
  • Crypto News
  • Team Portofolio (Premium)
  • Member Login

Copyright © 2024 Blog.cryptostudy.net | All Rights Reserved.