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