• About
  • FAQ
  • Earn Bitcoin while Surfing the net
  • Buy & Sell Crypto on Paxful
Newsletter
Approx Foundation
  • Home
    • Home – Layout 1
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Business
  • Guide
  • Contact Us
No Result
View All Result
  • Home
    • Home – Layout 1
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Business
  • Guide
  • Contact Us
No Result
View All Result
Approx Foundation
No Result
View All Result
Home Bitcoin

Broadcast Error RPC error: {“code”:-26,”message”:”non-mandatory-script-verify-flag (Invalid Schnorr signature)”}

Moussa by Moussa
November 28, 2024
in Bitcoin
0
peer discovery – how to obtain the IP addresses of nodes for mining pools?
189
SHARES
1.5k
VIEWS
Share on FacebookShare on Twitter


While broadcasting raw transaction has to chain, got the below error
RPC error: {“code”:-26,”message”:”non-mandatory-script-verify-flag (Invalid Schnorr signature)”} but signature verification method says its a valid signature for the given message.

I’m trying to do a simple taproot send transaction (key path spending). Signature is given by external signer

My data points are as below

{
  message: '60ccb78b5936d80f63c32eeafe9b746909d7e716f0f96988f437972e633ec7e0',
  signature: 'ed3061523f39137cdab4c9ca0bf9b62433b9642bb8165d996dcc120662866e8060e6f2314d7b03bab31f0a95b4574ddbed2892a176d2723810bd28fda66d1496',
  publicKey: 'ddb666300b8d7ef23e61e2ff3af3c70b59f882d6de1deb601590bb4d15b5d5d3'
}

Transaction hash

020000000001012bd272fa216d2370e265f591907266a8e76a26bc0be4318c9b1b340eaa6134860000000000ffffffff021027000000000000225120ddb666300b8d7ef23e61e2ff3af3c70b59f882d6de1deb601590bb4d15b5d5d3a8c8fa0200000000225120ddb666300b8d7ef23e61e2ff3af3c70b59f882d6de1deb601590bb4d15b5d5d30141ed3061523f39137cdab4c9ca0bf9b62433b9642bb8165d996dcc120662866e8060e6f2314d7b03bab31f0a95b4574ddbed2892a176d2723810bd28fda66d14960100000000

enter image description here

This is my entire code

import sha256 from "sha256";
import { Psbt, networks, payments, Transaction } from "bitcoinjs-lib";
import dotenv from 'dotenv';
import { verifySchnorrSignature } from "./mpc/address.js";
import { signBTCTransaction } from "./systemCallerUtils.js";
dotenv.config();

const UNCONFIRMED_HEIGHT = 4194303;

async function btcSendTransaction() {
  try {
    const address = process.env.BTC_ADDRESS;
    return await createSendTransaction(address);
  } catch (err) {
    console.error("Error in btcSendTransaction:", err);
    throw err;
  }
}

async function createSendTransaction(address) {
  const txObj = await handleTxObj(address);
  const { preSignTxHashes, psbt } = await generatePreSignTxHash(txObj);
  console.log("preSignTxHashes", preSignTxHashes);
  
  // Generate signatures for each input
  const generatedSigns = [];
  for (let i = 0; i < preSignTxHashes.length; i++) {
    const generatedSign = await signBTCTransaction(preSignTxHashes[i], "HASH");
    if (generatedSign) {
      generatedSigns.push(generatedSign);
    }
  }

  // Remove the '0x' prefix for verification
  const hashToVerify = preSignTxHashes[0].replace('0x', '');
  console.log('Hash for verification:', hashToVerify);
  
  try {
    const isValid = await verifySchnorrSignature(
      hashToVerify,
      generatedSigns[0].sign
    );
    console.log("Signature verification:", isValid);

    if (!isValid) {
      console.error('Verification failed:', {
        hash: hashToVerify,
        signature: generatedSigns[0].sign,
        pubkey: process.env.MPC_PUB_KEY
      });
      throw new Error('Invalid signature generated');
    }
  } catch (error) {
    console.error('Verification error:', error);
    throw error;
  }

  try {
    if (generatedSigns.length) {
      const response = await broadCastTx(generatedSigns, psbt);
      return response;
    }
  } catch (e) {
    console.error('Broadcast error:', e);
    throw e;
  }
}

const handleTxObj = async (address) => {
  try {
    let utxos = await getUtxos(address);
    utxos = utxos.filter((v) => v.height !== UNCONFIRMED_HEIGHT);
    
    const outputAmount = 10000;
    const feeRate = 200;
    const outputs = [{
      address: address,
      amount: outputAmount,
    }];

    const { selectedUtxos, totalValue } = selectUtxos(utxos, outputAmount + feeRate);

    console.log("selectedUtxos", selectedUtxos);

    return {
      fromAddress: address,
      utxos: selectedUtxos,
      outputs,
      feeRate,
      toAddress: address,
    };
  } catch (error) {
    console.error("handleTxObj error:", error);
    throw error;
  }
}

export function selectUtxos(utxos, targetAmount) {
  utxos.sort((a, b) => b.value - a.value);
  const selectedUtxos = [];
  let totalValue = 0;

  for (const utxo of utxos) {
    selectedUtxos.push(utxo);
    totalValue += utxo.value;
    if (totalValue >= targetAmount) break;
  }

  if (totalValue < targetAmount) {
    throw new Error('Insufficient UTXOs to cover the target amount');
  }

  return { selectedUtxos, totalValue };
}

export const generatePreSignTxHash = async (txObject) => {
  const network = networks.testnet;
  const psbt = new Psbt({ network });
  
  try {
    const { utxos, fromAddress, outputs, feeRate } = txObject;
    let inputSum = 0;
    const pubKey = process.env.MPC_PUB_KEY;
    const xOnlyPubKey = Buffer.from(pubKey, 'hex');

    // Add inputs using the actual UTXO script
    for (const utxo of utxos) {
      inputSum += utxo.value;
      
      // Get the actual UTXO details
      const txDetails = await fetch(`https://esplora.signet.surge.dev/tx/${utxo.txid}/hex`).then(r => r.text());
      const tx = Transaction.fromHex(txDetails);
      const outputScript = tx.outs[utxo.vout].script;
      
      console.log('UTXO details:', {
        script: outputScript.toString('hex'),
        value: utxo.value
      });

      psbt.addInput({
        hash: utxo.txid,
        index: utxo.vout,
        witnessUtxo: {
          script: outputScript,
          value: utxo.value,
        },
        tapInternalKey: xOnlyPubKey,
      });
    }

    // Add outputs
    for (const output of outputs) {
      psbt.addOutput({
        address: output.address,
        value: output.amount,
      });
    }

    // Add change output
    const totalOutputAmount = outputs.reduce((sum, output) => sum + output.amount, 0);
    const changeAmount = inputSum - totalOutputAmount - feeRate;

    if (changeAmount > 546) {
      psbt.addOutput({
        address: fromAddress,
        value: changeAmount,
      });
    }

    // Generate signing hashes
    const unsignedTx = Transaction.fromBuffer(psbt.data.globalMap.unsignedTx.toBuffer());
    const preSignTxHashes = psbt.data.inputs.map((input, index) => {
      const hash = unsignedTx.hashForWitnessV1(
        index,
        [input.witnessUtxo.script],
        [input.witnessUtxo.value],
        Transaction.SIGHASH_ALL
      );
      
      console.log('Input details:', {
        script: input.witnessUtxo.script.toString('hex'),
        value: input.witnessUtxo.value,
        hash: hash.toString('hex')
      });
      
      return `0x${hash.toString('hex')}`;
    });

    return { preSignTxHashes, psbt };
  } catch (error) {
    console.error('Error in generatePreSignTxHash:', error);
    throw error;
  }
};

export const broadCastTx = async (signatures, psbt) => {
  if (!signatures.length) {
    throw new Error('No signatures provided');
  }

  try {
    signatures.forEach((sig, index) => {
      const sigBuffer = Buffer.from(sig.sign.replace('0x', ''), 'hex');
      console.log(`Raw signature for input ${index}:`, sigBuffer.toString('hex'));
      console.log('Signature length:', sigBuffer.length);

      // For Taproot with SIGHASH_ALL
      const sigWithHashtype = Buffer.concat([
        sigBuffer,
        Buffer.from([Transaction.SIGHASH_ALL])
      ]);

      console.log(`Signature with hashtype for input ${index}:`, sigWithHashtype.toString('hex'));

      psbt.updateInput(index, {
        tapKeySig: sigWithHashtype
      });
    });

    psbt.finalizeAllInputs();
    const tx = psbt.extractTransaction(true);
    const rawTx = tx.toHex();
    
    console.log('Final transaction:', rawTx);
    console.log('Transaction details:', {
      version: tx.version,
      inputs: tx.ins.map(input => ({
        txid: input.hash.reverse().toString('hex'),
        vout: input.index,
        witness: input.witness.map(w => w.toString('hex'))
      })),
      outputs: tx.outs.map(output => ({
        value: output.value,
        script: output.script.toString('hex')
      }))
    });
    
    return await pushTx(rawTx);
  } catch (error) {
    console.error('Failed to broadcast transaction:', error);
    throw error;
  }
};

export const pushTx = async (rawtx) => {
  try {
    const endpoint="https://esplora.signet.surge.dev/tx";
    const resp = await fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "text/plain" },
      body: rawtx,
    });
    
    if (!resp.ok) {
      const errorText = await resp.text();
      throw new Error(`HTTP error! status: ${resp.status}, message: ${errorText}`);
    }
    
    const txid = await resp.text();
    return { txid };
  } catch (error) {
    console.error('Push transaction error:', error);
    throw error;
  }
};

export const getUtxos = async (address) => {
  try {
    const endpoint = `https://esplora.signet.surge.dev/address/${address}/utxo`;
    const resp = await fetch(endpoint, {
      method: "GET",
      headers: { "Content-Type": "application/json" },
    });
    if (!resp.ok) {
      throw new Error(`HTTP error! status: ${resp.status}`);
    }
    return await resp.json();
  } catch (error) {
    console.error('Get UTXOs error:', error);
    throw error;
  }
};

export { btcSendTransaction };

Can anyone help me with this?



Source link

Related articles

What The Coldcard Failure Teaches About Bitcoin Software Incentives

What The Coldcard Failure Teaches About Bitcoin Software Incentives

August 21, 2026
ARK’s Valente Sees RWA Trading Reshaping DeFi Platform Economics

ARK’s Valente Sees RWA Trading Reshaping DeFi Platform Economics

August 20, 2026
Share76Tweet47

Related Posts

What The Coldcard Failure Teaches About Bitcoin Software Incentives

What The Coldcard Failure Teaches About Bitcoin Software Incentives

by Moussa
August 21, 2026
0

Closed versus Open Source code has divided the Bitcoin and broader crypto industry for well over a decade. Bitcoin advocates...

ARK’s Valente Sees RWA Trading Reshaping DeFi Platform Economics

ARK’s Valente Sees RWA Trading Reshaping DeFi Platform Economics

by Moussa
August 20, 2026
0

Key TakeawaysSpecialized RWA venues could reduce the importance of major crypto pairs for venue success.Control of users and order flow...

Ethereum Jumps 18% As Spot Volume Surges Across Exchanges

Ethereum Jumps 18% As Spot Volume Surges Across Exchanges

by Moussa
August 20, 2026
0

Ethereum surged 18% intraday as spot trading volume jumped sharply across major global exchanges, putting ETH back at the center...

Iranian Hacking Crew Charged In Sprawling Theft Case — Including $6M Bitcoin Ransom

Iranian Hacking Crew Charged In Sprawling Theft Case — Including $6M Bitcoin Ransom

by Moussa
August 20, 2026
0

Feds have hit 17 Iranians with criminal charges for allegedly conducting a years-long campaign of cyber attacks — including trying...

Schiff Dismisses Bitcoin’s $72k Surge as Treasury-Fueled Fakeout

Schiff Dismisses Bitcoin’s $72k Surge as Treasury-Fueled Fakeout

by Moussa
August 20, 2026
0

Key TakeawaysTreasury doubled bond buybacks to $4B, triggering a bitcoin rally from under $65K to over $71K.Peter Schiff dismissed bitcoin’s...

Load More

youssufi.com

sephina.com

[vc_row full_width="stretch_row" parallax="content-moving" vc_row_background="" background_repeat="no-repeat" background_position="center center" footer_scheme="dark" css=".vc_custom_1517813231908{padding-top: 60px !important;padding-bottom: 30px !important;background-color: #191818 !important;background-position: center;background-repeat: no-repeat !important;background-size: cover !important;}" footer_widget_title_color="#fcbf46" footer_button_bg="#fcb11e"][vc_column width="1/4"]

We bring you the latest in Crypto News

[/vc_column][vc_column width="1/4"][vc_wp_categories]
[/vc_column][vc_column width="1/4"][vc_wp_tagcloud taxonomy="post_tag"][/vc_column][vc_column width="1/4"]

Newsletter

[vc_raw_html]JTNDcCUzRSUzQ2RpdiUyMGNsYXNzJTNEJTIydG5wJTIwdG5wLXN1YnNjcmlwdGlvbiUyMiUzRSUwQSUzQ2Zvcm0lMjBtZXRob2QlM0QlMjJwb3N0JTIyJTIwYWN0aW9uJTNEJTIyaHR0cHMlM0ElMkYlMkZhcHByb3gub3JnJTJGJTNGbmElM0RzJTIyJTNFJTBBJTBBJTNDaW5wdXQlMjB0eXBlJTNEJTIyaGlkZGVuJTIyJTIwbmFtZSUzRCUyMm5sYW5nJTIyJTIwdmFsdWUlM0QlMjIlMjIlM0UlM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1maXJzdG5hbWUlMjIlM0UlM0NsYWJlbCUyMGZvciUzRCUyMnRucC0xJTIyJTNFRmlyc3QlMjBuYW1lJTIwb3IlMjBmdWxsJTIwbmFtZSUzQyUyRmxhYmVsJTNFJTBBJTNDaW5wdXQlMjBjbGFzcyUzRCUyMnRucC1uYW1lJTIyJTIwdHlwZSUzRCUyMnRleHQlMjIlMjBuYW1lJTNEJTIybm4lMjIlMjBpZCUzRCUyMnRucC0xJTIyJTIwdmFsdWUlM0QlMjIlMjIlM0UlM0MlMkZkaXYlM0UlMEElM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1lbWFpbCUyMiUzRSUzQ2xhYmVsJTIwZm9yJTNEJTIydG5wLTIlMjIlM0VFbWFpbCUzQyUyRmxhYmVsJTNFJTBBJTNDaW5wdXQlMjBjbGFzcyUzRCUyMnRucC1lbWFpbCUyMiUyMHR5cGUlM0QlMjJlbWFpbCUyMiUyMG5hbWUlM0QlMjJuZSUyMiUyMGlkJTNEJTIydG5wLTIlMjIlMjB2YWx1ZSUzRCUyMiUyMiUyMHJlcXVpcmVkJTNFJTNDJTJGZGl2JTNFJTBBJTNDZGl2JTIwY2xhc3MlM0QlMjJ0bnAtZmllbGQlMjB0bnAtcHJpdmFjeS1maWVsZCUyMiUzRSUzQ2xhYmVsJTNFJTNDaW5wdXQlMjB0eXBlJTNEJTIyY2hlY2tib3glMjIlMjBuYW1lJTNEJTIybnklMjIlMjByZXF1aXJlZCUyMGNsYXNzJTNEJTIydG5wLXByaXZhY3klMjIlM0UlQzIlQTBCeSUyMGNvbnRpbnVpbmclMkMlMjB5b3UlMjBhY2NlcHQlMjB0aGUlMjBwcml2YWN5JTIwcG9saWN5JTNDJTJGbGFiZWwlM0UlM0MlMkZkaXYlM0UlM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1idXR0b24lMjIlM0UlM0NpbnB1dCUyMGNsYXNzJTNEJTIydG5wLXN1Ym1pdCUyMiUyMHR5cGUlM0QlMjJzdWJtaXQlMjIlMjB2YWx1ZSUzRCUyMlN1YnNjcmliZSUyMiUyMCUzRSUwQSUzQyUyRmRpdiUzRSUwQSUzQyUyRmZvcm0lM0UlMEElM0MlMkZkaXYlM0UlM0NiciUyRiUzRSUzQyUyRnAlM0U=[/vc_raw_html][/vc_column][/vc_row]
No Result
View All Result
  • Contact Us
  • Homepages
  • Business
  • Guide

© 2024 APPROX FOUNDATION - The Crypto Currency News