20 从P2SH/P2WSH转出BTC,使用bitcoinjs-lib构建交易出错

无法将脚本中的BTC转出,在构建tx出错。

1、首先构建一个脚本,该脚本只需要验证notary签名;

const script = bitcoin.script.compile([
    Buffer.from(notary.publicKey),
    bitcoin.opcodes.OP_CHECKSIGVERIFY,
]);
const Script = bitcoin.payments.p2wsh({
    redeem: { output: script, network: testnet },
    network: testnet,
});

2、向该脚本的地址转账(附带了OP_RETURN)(https://blockstream.info/testnet/address/tb1q922u48aatmh3vynxtwwfls4pamt7scu5vdv9j8u3ufe95ag463kqgqaccg);

3、从脚本转出BTC;psbt.finalizeAllInputs()错误:"Can not finalize input #0"

查看了bitcoinjs-lib(6.1.6)源码,是没有获取到witnessScript的类型。代码如下:

const { notary, network } = getAccount();
const notaryWIF = notary.toWIF();
const notaryTaprootAddress = bitcoin.payments.p2tr({
    internalPubkey: toXOnly(notary.publicKey),
    network: network
});
console.log(notaryTaprootAddress.address)
// tb1p83s4r6e07aeeks4l8f996ylu6v07mxmykawzylggqwytnvhck49sham65n

// 生成脚本地址
const script = bitcoin.script.compile([
    Buffer.from(notary.publicKey),
    bitcoin.opcodes.OP_CHECKSIGVERIFY,
]);
const Script = bitcoin.payments.p2wsh({
    redeem: { output: script, network: testnet },
    network: testnet,
});
const scriptAddress = Script.address
console.log(scriptAddress);
// P2WSH:tb1q922u48aatmh3vynxtwwfls4pamt7scu5vdv9j8u3ufe95ag463kqgqaccg

const sendBtcFromP2SH = async (p2shAddress, toAddress, amount) => {
    const keyPair = ECPair.fromWIF(notaryWIF, testnet);

    const psbt = new bitcoin.Psbt({ network: testnet })

    const fee = 500; // 设置手续费
    const utxos = await rpcUnisats.getAddressUtxos(p2shAddress);
    let inputAmount = 0;

    for (const utxo of utxos) {
        // const txHex = await rpcMempool.getTransactionHex(utxo.txId)
        psbt.addInput({
            hash: utxo.txId,
            index: utxo.outputIndex,
            // nonWitnessUtxo: Buffer.from(txHex,'hex'),
            witnessUtxo: {
                script: Script.output,
                value: utxo.satoshis,
            },
            witnessScript: Script.redeem.output, // todo
        });
        inputAmount += utxo.value;
        if (inputAmount >= fee + amount) {
            break;
        }
    }
    psbt.addOutput({ address: toAddress, value: amount });
    const changeAmount = inputAmount - amount - fee;
    if (changeAmount < 0) {
        console.log('btcBridge::sentOutgoingBTC Not enough funds to cover the transaction');
        return;
    }
    if (changeAmount > 0) {
        psbt.addOutput({ address: p2shAddress, value: changeAmount });
    }

    // 使用notary的私钥来签名交易   

    psbt.signAllInputs(keyPair);
    psbt.finalizeAllInputs(); // 出错行

    const tx = psbt.extractTransaction();
    const txHex = tx.toHex();

    // broadcast tx
}

sendBtcFromP2SH(scriptAddress, 'receiver_address', libBitcoin.convertBtc2Satoshi("0.00000001"))

同时也试过使用脚本的P2SH地址,得到同样的错误,代码如下:

const Script = bitcoin.payments.p2sh({
    redeem: { output: script, network: testnet },
    network: testnet,
});
//2NF41qsRtKexTNFxF1uDVQNrUWvkcpcuQiq

....

for (const utxo of utxos) {
        const txHex = await rpcMempool.getTransactionHex(utxo.txId)
        psbt.addInput({
            hash: utxo.txId,
            index: utxo.outputIndex,
            nonWitnessUtxo: Buffer.from(txHex,'hex'),
            redeemScript:Script.redeem.output, 
        });
        inputAmount += utxo.value;
        if (inputAmount >= fee + amount) {
            break;
        }
    }
请先 登录 后评论

1 个回答

axengine
请先 登录 后评论
  • 1 关注
  • 0 收藏,1175 浏览
  • axengine 提出于 2024-08-28 15:14