• 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

Blackrock Crypto Buying Spree: $3Bn BTC USD Added in March

Blackrock Crypto Buying Spree: $3Bn BTC USD Added in March

April 4, 2026
If Dogecoin Breaks Through This Sell Wall, Expect A Pump

If Dogecoin Breaks Through This Sell Wall, Expect A Pump

April 3, 2026
Share76Tweet47

Related Posts

Blackrock Crypto Buying Spree: $3Bn BTC USD Added in March

Blackrock Crypto Buying Spree: $3Bn BTC USD Added in March

by Moussa
April 4, 2026
0

The BlackRock crypto experiment is chugging along at an incredible pace after the world’s largest asset manager added more than...

If Dogecoin Breaks Through This Sell Wall, Expect A Pump

If Dogecoin Breaks Through This Sell Wall, Expect A Pump

by Moussa
April 3, 2026
0

Trusted Editorial content, reviewed by leading industry experts and seasoned editors. Ad Disclosure The Dogecoin (DOGE) price has been in...

Inside Binance’s Gold And Oil Rush — Are Whales Bracing For A Crypto Shock?

Inside Binance’s Gold And Oil Rush — Are Whales Bracing For A Crypto Shock?

by Moussa
April 3, 2026
0

Gold (XAU) and silver (XAG) futures have climbed into the top five by trading volume on Binance Futures. Binance Metal...

Charles Schwab Signals Direct Bitcoin Trading Push

Charles Schwab Signals Direct Bitcoin Trading Push

by Moussa
April 3, 2026
0

Financial services giant Charles Schwab is preparing to expand deeper into digital assets, announcing plans for a forthcoming product that...

Bitcoin Hovers Near $67,000 Amid US Political Turmoil and Soaring Energy Prices – Markets and Prices Bitcoin News

Bitcoin Hovers Near $67,000 Amid US Political Turmoil and Soaring Energy Prices – Markets and Prices Bitcoin News

by Moussa
April 3, 2026
0

Political Turbulence Overshadows Conflict Bitcoin traded mostly flat on Friday as market attention pivoted from Middle Eastern hostilities toward significant...

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