I’m trying to follow the below transaction example by magic eden and extend it to support multiple buyers and seller (in red). However I am having difficulties when I add more than one signature from another party (with one seller it broadcasts okay). The transaction builds and signs fine but when I try to broadcast it to the network it results in the error mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)
. Using native segwit addresses for this (no-tr).
What am I missing or doing wrong?
Using the bitcoinjs library here is what I have so far (only the red):
Seller signing:
let psbt = new bitcoin.Psbt({ network });
const [ordinalUtxoTxId, ordinalUtxoVout] = ordinalOutput.split(":");
const tx = bitcoin.Transaction.fromHex(await getTxHexById(ordinalUtxoTxId));
try {
tx.setWitness(parseInt(ordinalUtxoVout), []);
} catch {}
const input = {
hash: ordinalUtxoTxId,
index: parseInt(ordinalUtxoVout),
nonWitnessUtxo: tx.toBuffer(),
witnessUtxo: tx.outs[ordinalUtxoVout],
sighashType:
bitcoin.Transaction.SIGHASH_SINGLE |
bitcoin.Transaction.SIGHASH_ANYONECANPAY,
};
psbt.addInput(input);
psbt.addOutput({
address: paymentAddress,
value: price,
});
Buyer Signing (ignoring padding inputs and outputs):
// Add inscriptions inputs and outputs
for (const signedPsbt of sellerSignedPsbts) {
// Add inscription output
psbt.addOutput({
address: receiverAddress,
value: signedPsbt.data.inputs[0].witnessUtxo.value,
});
// Add payer signed input
psbt.addInput({
...signedPsbt.data.globalMap.unsignedTx.tx.ins[0],
// ...signedPsbt.data.inputs[0],
witnessUtxo: signedPsbt.data.inputs[0].witnessUtxo,
nonWitnessUtxo: signedPsbt.data.inputs[0].nonWitnessUtxo,
// finalScriptWitness: signedPsbt.data.inputs[0].finalScriptWitness,
});
input++;
}
// Add seller payment outputs for payee
for (const signedPsbt of sellerSignedPsbts) {
// Add payer output
psbt.addOutput({
...signedPsbt.data.globalMap.unsignedTx.tx.outs[0],
});
}
Merge seller and buyer signed psbts:
const buyerSignedPsbt = bitcoin.Psbt.fromBase64(signedBuyingPSBTBase64);
for (let index = 0; index < signedListingsPSBTBase64.length; index++) {
const sellerSignedPsbt = bitcoin.Psbt.fromBase64(signedListingsPSBTBase64[index]);
buyerSignedPsbt.data.globalMap.unsignedTx.tx.ins[BUYING_PSBT_SELLER_SIGNATURE_INDEX + index] = sellerSignedPsbt.data.globalMap.unsignedTx.tx.ins[0];
buyerSignedPsbt.data.inputs[BUYING_PSBT_SELLER_SIGNATURE_INDEX + index] = sellerSignedPsbt.data.inputs[0];
}
// broadcast buyerSignedPsbt