I am having a difficult time figuring out how to sign a spend from a change address. I get Error: cannot sign for this input with the key <value>
. The initial transaction works fine, where I generate a transaction with multiple inputs to two outputs, one of them being the change address - it is the same as the spender addresses. Here are the steps:
1) I grab all UTXO for our spending address.
const unspentTx = (await listUnspentTxByAddresses([mainAddress])).data.result;
2) I add all inputs and outputs, sign, finalize, and submit.
const fee = new BigNumber((await getEstimateSmartFee(2)).data.result.feerate)
.times(100000000)
.div(3);
const output = {
address: destinationAddress,
value: parseInt(pullAmount.minus(fee).toFixed(0)),
};
const senderBalance = sum
.times(100000000)
.minus(pullAmount)
.minus(fee);
const change = {
address: sender,
value: parseInt(senderBalance.toString()),
};
// Adding the output
psbt.addOutput(output);
psbt.addOutput(change);
for (let i = 0; i < txids.length; i++) {
const transactionObject = await getTransaction(txids[i]);
const input = {
hash: txids[i],
index: 0,
nonWitnessUtxo: Buffer.from(transactionObject.data.result.hex, 'hex'),
};
try {
psbt.addInput(input);
} catch (e) {
console.log('Add Input Failed e =>', e);
return null;
}
}
const key = bitcoin.ECPair.fromWIF(privateKey, testnet);
for (let i = 0; i < txids.length; i++) {
psbt.signInput(i, key);
}
psbt.finalizeAllInputs();
const rawTx = psbt.extractTransaction().toHex();
const withdrawPendingTx = await sendRawTransaction(rawTx);
This works the first time around, but as mentioned, the second time I call
await listUnspentTxByAddresses([mainAddress])
and follow the same exact procedure, the js library validation prevents signing with the main address key. It doesn't seem to make sense, so I hope there is an obvious error here. I'm pretty sure it's sent as a default P2PKH with SigHashAll.