Can't sign the taproot PSBT with the leafKey

I tried to make two transactions, the Tx1 I have made is a taproot output. I wanted to create second Tx2 to use the output Tx1. But I always couldn't sign the PSBT. If you can help me, thank you very much. Here are my codes.

import bitcoin, { script } from 'bitcoinjs-lib';
import { ECPairFactory } from 'ecpair'
import ecc from '@bitcoinerlab/secp256k1';
const { networks } = bitcoin;
import path from 'path';
import fs from 'fs'; // 添加文件系统模块
import crypto from 'crypto'; // 引入crypto模块生成随机数
import { toXOnly, tapTreeToList } from 'bitcoinjs-lib/src/psbt/bip371.js';
// 添加 BIP32 模块
import BIP32Factory from 'bip32';
import * as tools from 'uint8array-tools';



// 正确初始化 ECC 库
bitcoin.initEccLib(ecc);
// 初始化 ECPair
const ECPair = ECPairFactory(ecc);
// 初始化 BIP32
const bip32 = BIP32Factory(ecc); // 使用 ECC 库初始化 bip32
// 配置为测试网
const network = networks.testnet;
// 定义随机数生成函数
const rng = () => crypto.randomBytes(64);

const privateKeyWIF = '';// 2Ms...
const privateKeyPair = ECPair.fromWIF(privateKeyWIF, network);

// 生成密钥
const internalKey = bip32.fromSeed(rng(), network);// for key path
const leafKey = bip32.fromSeed(rng(), network);// for script path

const leafXOnlyPubkey = toXOnly(leafKey.publicKey);

console.log('XOnly Pubkey of leafKey: ',leafXOnlyPubkey);
console.log('tools.toHex(leafECPair.publicKey) ',tools.toHex(leafXOnlyPubkey));


const str = 'today is May 16th in 2025';// 构造要插入的数据
const data = Buffer.from(str,'utf8');

const leafScript = bitcoin.script.compile([
  Buffer.from(tools.toHex(leafXOnlyPubkey)),
  bitcoin.opcodes.OP_CHECKSIG,
  bitcoin.opcodes.OP_0,
  bitcoin.opcodes.OP_IF,
    data,
  bitcoin.opcodes.OP_ENDIF
]);



const scriptTree = [
    {
        output: bitcoin.script.fromASM(
                    '0238f2a4a57b510431bb835d9e46e1c946190a084828521195f77aa23c7efb438c OP_CHECKSIG',
                  ),
    },
    {
        output: leafScript,
    },
];
// ???
const redeem = {
      output: leafScript,
      redeemVersion: 192, // LEAF_VERSION_TAPSCRIPT = 192
    };

// 创建一个taproot的p2tr对象
console.log('toXonly the internalKey.publicKey :',toXOnly(internalKey.publicKey))
const p2trObject = bitcoin.payments.p2tr({
    internalPubkey: Buffer.from(toXOnly(internalKey.publicKey)),
    scriptTree,
    redeem:{output: leafScript, redeemVersion: 192 },// LEAF_VERSION_TAPSCRIPT = 192
    network: network,
})

console.log('Taproot Address:',p2trObject.address);

//=========create the 1st Tx1================
const txid = 'b8433aa5addd2a0d715a5b720b661088cd77e14b9e7862dd7117040415390523';
const vout = 0; // 确认UTXO的vout索引
const privateKey = '';// 2Ms...
const redeemScriptHex = '00148d07de8df8f6c64ce9ef542f9e32b6d8517aac3f'; // 例如:'522102...ae'
// const redeemScriptHex = '00147b0e1b7b4e0c2d4d0d7b2f6ce0d5ca4e7f4ed38e'; // 例如:'522102...ae'
const scriptPubKey = 'a914011beb6fb8499e075a57027fb0a58384f2d3f78487';
const utxoValue = 39062500; // UTXO的金额(satoshis)
const fee = 1000; // 手续费(satoshis)

const psbt1 = new bitcoin.Psbt({ network });
// 添加输入
psbt1.addInput({
    hash: txid,
    index: vout,
    witnessUtxo: {
      script: Buffer.from(scriptPubKey, 'hex'), // 
      value: utxoValue,
    },
    redeemScript: Buffer.from(redeemScriptHex, 'hex'),
});

// 添加输出
// console.log('internalKey.publicKey is :',internalKey.publicKey);*** Unit8Array(32)***
// console.log('Buffer from internalKey.publicKey is :',Buffer.from(internalKey.publicKey));  ***Unit8Array(32)***

psbt1.addOutput({
    address: p2trObject.address,
    value: utxoValue - fee, // 扣除手续费
    tapInternalKey: Buffer.from(toXOnly(internalKey.publicKey)),
    tapTree: {leaves:tapTreeToList(scriptTree)},
  });

console.log('privateKeyPair :',privateKeyPair);


// psbt1.signInput(0,privateKeyPair);
psbt1.signInput(0, {
  publicKey: Buffer.from(privateKeyPair.publicKey),
  sign: (hash) => {
      const signature = privateKeyPair.sign(hash);
      return Buffer.from(signature); 
  },
});

psbt1.finalizeInput(0);
const tx1 = psbt1.extractTransaction();
// get rawTransaction
const rawTx1 = tx1.toBuffer();
const hex1 = tools.toHex(rawTx1);
console.log('第一个交易是:',hex1);
// get txid
const txid1 = tx1.getId();
console.log('第一个交易的 txid 是:', txid1);


const amount = 39061500;// 39062500 - 1000
const sendAmount = amount - fee;
// ===================== create the 2nd Tx2 ================
const psbt2 = new bitcoin.Psbt({network});
// 添加输入
psbt2.addInput({
    hash: txid1,
    index: 0,
    witnessUtxo: { value: amount, script: p2trObject.output},
})
console.log('psbt2 added Input,psbt2 :',psbt2);
psbt2.updateInput(0, {
    tapLeafScript: [
      {
        leafVersion: redeem.redeemVersion,
        script: redeem.output,
        controlBlock: p2trObject.witness[p2trObject.witness.length - 1],
      },
    ],
  });
console.log('psbt2 updated Input,psbt2 :',psbt2)

// 创建输出的taproot地址
const sendInternalKey = bip32.fromSeed(rng(), network);

const { address: sendAddress } = bitcoin.payments.p2tr({
        internalPubkey: Buffer.from(toXOnly(sendInternalKey.publicKey)),
        scriptTree,
        network: network,
      });
// 添加输出
psbt2.addOutput({
      value: sendAmount,
      address: sendAddress,
      tapInternalKey: Buffer.from(toXOnly(sendInternalKey.publicKey)),
      tapTree: {leaves: tapTreeToList(scriptTree)},
    });


// !!!!!!!
psbt2.signInput(0, leafKey);// always wrong!!!
// !!!!!!!

then the problem may be about the key. The error is :

 throw new Error(
            ^

Error: Can not sign for input #0 with the key 2,124,105,49,150,91,89,124,2,240,145,242,150,205,131,44,59,194,222,169,8,8,246,81,238,28,73,195,177,158,148,9,79
    at Psbt.checkTaprootHashesForSig (C:\Users\sheng.wang01\personal_doc\network_python\scripts\bitcoinjs\node_modules\bitcoinjs-lib\src\psbt.js:854:13)
    at Psbt._signTaprootInput (C:\Users\sheng.wang01\personal_doc\network_python\scripts\bitcoinjs\node_modules\bitcoinjs-lib\src\psbt.js:692:31)
    at Psbt.signInput (C:\Users\sheng.wang01\personal_doc\network_python\scripts\bitcoinjs\node_modules\bitcoinjs-lib\src\psbt.js:640:19)


from Recent Questions - Bitcoin Stack Exchange https://ift.tt/fgCorFz
via IFTTT

Popular posts from this blog

Future of Bitcoin encryption and security in a QC era

Possible rollback due to lazy reveal in BRC20?

A way to recover scammed Bitcoin investment